Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/448.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 你能不用延期付款就写这个吗?_Javascript_Node.js_Promise_Deferred - Fatal编程技术网

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-我更感兴趣的是,是否有一种不同的方式来实现这个接口,而不必解决来自执行者外部的承诺。我看到人们对延迟解决方案的概念不屑一顾,我想知道是否有一个好的替代方案可以替代使用延迟解决方案。啊,我明白了。我不确定有没有。除非大脑现在让我失望,否则如果它必须在执行者内部,这似乎是一个鸡和蛋的问题,因为你需要知道什么时候解决,但你不知道什么时候创造承诺。也许可以使用不同的构造。类似于表示异步操作而不是值的未来/任务。但我不是很确定