gpt4 book ai didi

javascript - 你能在不使用 Deferred 的情况下写这个吗?

转载 作者:行者123 更新时间:2023-12-02 16:42:22 25 4
gpt4 key购买 nike

我在下面写了一些使用 promise 的代码,我能找到的最简单的编写方法是使用 Deferred 对象而不是通常的 Promise 执行器函数,因为我需要从外部解析 promise执行人。我想知道是否有一个基于 Promise 执行程序函数的公认设计模式来解决这样一个不使用类似延迟的解决方案的问题?是否可以在不必从 promise 执行者外部解决 promise 的情况下完成?

这里是详细信息。

我有一个项目使用了一组工作线程,代码的各个部分时不时要使用一个工作线程。为了管理它,我创建了一个简单的 WorkerList 类,它保留可用工作线程的列表。当有人想要使用它时,他们会对其调用 get() 并返回一个解析为工作线程的 promise 。如果工作线程立即可用,则 promise 立即解决。如果所有工作线程都在使用中(因此可用工作线程列表为空),则 promise 不会解决,直到稍后通过 add(worker) 方法将一个线程放回可用列表中.

这个 WorkerList 类只有两个方法,add(worker)get()。你 get() 一个 worker ,当你完成它时,你 add(worker) 它回来。当您 add(worker) 返回时,该类会检查是否有任何任务在等待可用的 Worker。如果有,它会解决他们与可用 Worker 的 promise 。解决别人的 promise 就是使用 Deferred 的地方。

这是 WorkerList 的代码:

class WorkerList {
constructor() {
this.workers = [];
this.deferredQueue = [];
}
add(worker) {
this.workers.push(worker);

// if someone is waiting for a worker,
// pull the oldest worker out of the list and
// give it to the oldest deferred that is waiting
while (this.deferredQueue.length && this.workers.length) {
let d = this.deferredQueue.shift();
d.resolve(this.workers.shift());
}
}
// if there's a worker, get one immediately
// if not, return a promise that resolves with a worker
// when next one is available
get() {
if (this.workers.length) {
return Promise.resolve(this.workers.shift());
} else {
let d = new Deferred();
this.deferredQueue.push(d);
return d.promise;
}
}
}

还有,这里是延迟实现:

function Deferred() {
if (!(this instanceof Deferred)) {
return new Deferred();
}
const p = this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
this.then = p.then.bind(p);
this.catch = p.catch.bind(p);
if (p.finally) {
this.finally = p.finally.bind(p);
}
}

最佳答案

也许下面只是一个可怜人处理延迟的方法,并没有真正触及问题的症结所在,但是您可以保留一个解析器函数队列,而不是一个延迟队列。

这会比您的方法节省少量代码,并避免显式使用 Deferreds。

我不知道是否有针对此的既定模式,但这本身似乎是一种用于维护异步对象池的可重用模式,因此与其将其称为 WorkerList,不如将其称为 WorkerList将其命名为 AsyncPool,然后将其组合为 WorkerList 中的可重用部分:

class AsyncPool {
constructor() {
this.entries = [];
this.resolverQueue = [];
}
add(entry) {
console.log(`adding ${entry}`);
this.entries.push(entry);

// if someone is waiting for an entry,
// pull the oldest one out of the list and
// give it to the oldest resolver that is waiting
while (this.resolverQueue.length && this.entries .length) {
let r = this.resolverQueue.shift();
r(this.entries.shift());
}
}
// if there's an entry, get one immediately
// if not, return a promise that resolves with an entry
// when next one is available
get() {
return new Promise((r) =>
this.entries.length
? r(this.entries.shift())
: this.resolverQueue.push(r)
);
}
}


let pool = new AsyncPool();

pool.add('Doc');
pool.add('Grumpy');
pool.get().then(console.log);
pool.get().then(console.log);
pool.get().then(console.log);
pool.get().then(console.log);

// add more entries later
setTimeout(() => pool.add('Sneezy'), 1000);
setTimeout(() => pool.add('Sleepy'), 2000);

关于javascript - 你能在不使用 Deferred 的情况下写这个吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61358448/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com