【发布时间】:2020-08-05 01:54:53
【问题描述】:
我在下面编写了一些使用 Promise 的代码,我能找到的最简单的编写方法是使用 Deferred 对象而不是通常的 Promise 执行器函数,因为我需要从执行器外部解析 Promise。我想知道是否有一个基于 Promise 执行器函数的公认设计模式来解决这样的问题,它不使用类似延迟的解决方案?是否可以在无需从 Promise Executor 外部解决 Promise 的情况下完成?
这里是详细信息。
我有一个项目使用一组工作线程和想要不时使用工作线程的代码的各个部分。为了管理它,我创建了一个简单的WorkerList 类,它保留了可用工作线程的列表。当有人想要使用一个时,他们会调用get() 并返回一个解析为工作线程的承诺。如果工作线程立即可用,则承诺立即解决。如果所有工作线程都在使用中(因此可用工作线程列表为空),则承诺不会解析,直到稍后通过add(worker) 方法将一个返回可用列表。
这个 WorkerList 类只有两个方法,add(worker) 和 get()。你get() 一个工人,当你完成它时,你add(worker) 它回来了。当您add(worker) 回来时,该类会检查是否有任何任务在等待可用的 Worker。如果有,它会通过可用的 Worker 解决他们的承诺。解决其他人的承诺就是使用 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);
}
}
【问题讨论】:
-
对不起,如果这看起来很愚蠢 - 我正在等待咖啡开始。我读对了吗 -
Deferred基本上是一个无参数的Promise用于解决/拒绝它在执行人之外?所以,问题是“有没有一种标准的方法可以从执行者外部解决 Promise”? -
@VLAZ - 我更感兴趣的是是否有不同的方法来实现这个接口,而不必从执行程序外部解决承诺。我看到人们抛弃了延迟的概念,我想知道是否有一个很好的替代方案来替代使用类似延迟的解决方案。
-
啊,我明白了。我不确定有没有。除非大脑现在让我失望,否则如果它必须在 executor 内部,这似乎是鸡和蛋的问题,因为你需要知道何时解决,但你不知道何时创建 Promise。也许可以使用不同的构造。类似于 Future/Task 的东西,它代表一个异步 操作 而不是一个值。但我不太确定最好的方法是什么。
-
@VLAZ - 我想象从
EventEmitter派生并让.add()发出承诺执行者正在监听的东西,但我不确定如何保持整个系统的先进先出,因为每次等待promise 会监听同一个事件,它很快看起来比这里的要复杂。 -
@grodzi - 如果没有人在这两种方法之外弄乱实例变量,则不需要 while 循环。但是,我确实想象了一个可以预填充实例数据的构造函数。所以,我认为
while循环实际上只是一个简单的if的代码,所以我这样说。
标签: javascript node.js promise deferred