Javascript 你能不用延期付款就写这个吗?
我在下面编写了一些使用承诺的代码,我能找到的最简单的编写方法是使用Javascript 你能不用延期付款就写这个吗?,javascript,node.js,promise,deferred,Javascript,Node.js,Promise,Deferred,我在下面编写了一些使用承诺的代码,我能找到的最简单的编写方法是使用Deferred对象,而不是通常的承诺执行器函数,因为我需要从执行器外部解析承诺。我想知道,对于这样的问题,是否有一种基于Promise executor函数的可接受的设计模式不使用延迟式解决方案?不必从承诺执行人以外的人处解决承诺,是否可以做到这一点 详情如下 我有一个项目,它使用一组工作线程和代码的各个部分,这些部分希望不时使用工作线程。为了解决这个问题,我创建了一个简单的WorkerList类,它保存了可用工作线程的列表。当
Deferred
对象,而不是通常的承诺执行器函数,因为我需要从执行器外部解析承诺。我想知道,对于这样的问题,是否有一种基于Promise executor函数的可接受的设计模式不使用延迟式解决方案?不必从承诺执行人以外的人处解决承诺,是否可以做到这一点
详情如下
我有一个项目,它使用一组工作线程和代码的各个部分,这些部分希望不时使用工作线程。为了解决这个问题,我创建了一个简单的WorkerList
类,它保存了可用工作线程的列表。当有人想要使用它时,他们会对它调用get()
,并返回一个解析为工作线程的承诺。如果工作线程立即可用,承诺将立即解决。如果所有工作线程都在使用中(因此可用工作线程的列表为空),那么直到稍后通过add(worker)
方法将一个线程放回可用列表中,承诺才会解决
这个WorkerList类只有两个方法,add(worker)
和get()
。你get()
一个工人,当你完成了它,你add(worker)
它回来了。当您add(worker)
it back时,类将检查是否有任何任务等待可用的worker。如果有,它将与可用的工人解决他们的承诺。对他人承诺的解决就是延迟的使用
以下是工作列表的代码:
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);
}
}
也许下面的内容只是一个穷人处理延迟的方法,并没有真正触及问题的关键,但是您可以保留一个冲突解决程序函数队列,而不是延迟队列
这在您的方法上节省了少量代码,并避免了显式使用延迟
我不知道这是否有一个既定的模式,但这本身似乎是一个用于维护异步对象池的可重用模式,因此,您可以将其命名为AsyncPool
,然后在工作列表中将其作为一个可重用的部分组成:
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;
}
}
}
类异步池{
构造函数(){
this.entries=[];
this.resolverQueue=[];
}
添加(条目){
log(`adding${entry}`);
这个.entries.push(entry);
//如果有人在等待进入,
//从列表中拉出最旧的一个,然后
//将其交给正在等待的最旧解析程序
while(this.resolverQueue.length&&this.entries.length){
设r=this.resolverQueue.shift();
r(this.entries.shift());
}
}
//如果有条目,请立即获取
//如果不是,则返回一个通过条目解析的承诺
//下一个何时可用
得到(){
返回新承诺((r)=>
这是长度
?r(this.entries.shift())
:this.resolverQueue.push(r)
);
}
}
让池=新的异步池();
添加('Doc');
pool.add('Grumpy');
pool.get().then(console.log);
pool.get().then(console.log);
pool.get().then(console.log);
pool.get().then(console.log);
//稍后添加更多条目
setTimeout(()=>pool.add('sneegy'),1000);
setTimeout(()=>pool.add('Sleepy'),2000)代码>这里有一个解决方案,它不会在promise executor函数之外的任何地方公开promise resolver函数
下面是我对自己关于基于事件的解决方案的问题的评论。它使用触发事件和事件侦听器在promise executor函数中引发操作
class WorkerList extends EventEmitter {
constructor() {
this.workers = [];
}
add(worker) {
this.workers.push(worker);
// notify listeners that there's a new worker in town
this.emit('workerAdded');
}
// 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 {
return new Promise(resolve => {
const onAdded = () => {
if (this.workers.length) {
this.off('workerAdded', onAdded);
resolve(this.workers.shift());
}
}
this.on('workerAdded', onAdded);
});
}
}
}
我最初关心的是维护FIFO顺序,以便第一个调用get()
的调用方可以获得下一个可用的工作方。但是,因为eventListeners是按添加顺序调用的,所以我认为这实际上可以实现FIFO顺序。如果有多个对get()
的调用,它们都会收到有关添加的workerAdded
的通知,但在第一个调用处理消息并接收worker之后,其他人只会发现没有工作人员留给他们,所以他们的侦听器将保持连接,等待将来有工作人员给他们时(当他们的侦听器排在第一位时)出现一条添加了工作人员的消息
我不认为我一定比所示的其他选项更喜欢它,但它是一种替代方法,不使用延迟,甚至不在executor函数之外公开resolve
处理程序
class WorkerList extends EventEmitter {
constructor() {
this.workers = [];
}
add(worker) {
this.workers.push(worker);
// notify listeners that there's a new worker in town
this.emit('workerAdded');
}
// 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 {
return new Promise(resolve => {
const onAdded = () => {
if (this.workers.length) {
this.off('workerAdded', onAdded);
resolve(this.workers.shift());
}
}
this.on('workerAdded', onAdded);
});
}
}
}
正如所建议的,如果eventEmitter是实例变量而不是基类,也可以这样做:
class WorkerList {
constructor() {
this.workers = [];
this.emitter = new EventEmitter();
}
add(worker) {
this.workers.push(worker);
// notify listeners that there's a new worker in town
this.emitter.emit('workerAdded');
}
// 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 {
return new Promise(resolve => {
const onAdded = () => {
if (this.workers.length) {
this.emitter.off('workerAdded', onAdded);
resolve(this.workers.shift());
}
}
this.emitter.on('workerAdded', onAdded);
});
}
}
}
对不起,如果这看起来很愚蠢的话,我在等咖啡来。我读对了吗?延迟
基本上是一个无参数的承诺
,您用来从执行者外部解决/拒绝它?所以,问题是“是否有一种标准的方式来解决来自执行者外部的承诺”@VLAZ-我更感兴趣的是,是否有一种不同的方式来实现这个接口,而不必解决来自执行者外部的承诺。我看到人们对延迟解决方案的概念不屑一顾,我想知道是否有一个好的替代方案可以替代使用延迟解决方案。啊,我明白了。我不确定有没有。除非大脑现在让我失望,否则如果它必须在执行者内部,这似乎是一个鸡和蛋的问题,因为你需要知道什么时候解决,但你不知道什么时候创造承诺。也许可以使用不同的构造。类似于表示异步操作而不是值的未来/任务。但我不是很确定