在存在之前等待承诺

我正在听用户事件,其中一些取决于其他人的完成 。 处理这些事件是一个asynchronous的任务 ,所以我使用承诺

比方说,我有这个:

A -> B -> C -> ... -> D -> E -> ... -> F 

我最初的做法是为A保存一个承诺,并使用A的承诺的方法附加B的处理。 BCDDEF

但是这些事件几乎可以在同一时间发生B可以在A之前发生 。 既然我不能听一个不存在的承诺 ……你将如何解决这个问题?

我的想法是为每个级别(A,B,D) 定义一个对象 ,在这里我可以附加一个承诺处理未来事件 。 当附上一个承诺时 ,我会重复处理未来的事件,然后将它们设置为诺言。 当附加未来的事件时 ,我会看看是否有承诺,并将其附加到它,或将其保存到数组或其他东西。

您是否知道已经解决了这个问题的现有解决scheme,还是应该遵循我的想法?

谢谢。


按要求进一步澄清:

我正在监听通过websocket(使用socket.io)转发到服务器的客户端多媒体事件。 事件的顺序确实是第一个A,然后是B等等,但是由于它们中的一些几乎同时发生,所以它们可以不按顺序处理。

示例代码

 let promiseForA, promiseForB; socket.on('A', data => { promiseForA = asynchronousTaskForA(); }); socket.on('B', data => { // What if promiseForA has not yet been defined? promiseForA.then(neededValue => { asynchronousTaskForB(neededValue); }); }); socket.on('C', data => { // What if promiseForB has not yet been defined? promiseForB.then(neededValue => { asynchronousTaskForC(neededValue); }); }); socket.on('D', data => { // What if promiseForB has not yet been defined? promiseForB.then(neededValue => { asynchronousTaskForD(neededValue); }); }); function asynchronousTaskForA() { // something resolve('something needed by B'); } function asynchronousTaskForB(value) { // something with value resolve('something needed by C ... D'); } function asynchronousTaskForC(value) { // something with value resolve(); } function asynchronousTaskForD(value) { // something with value resolve('something needed by E ... F'); } 

我的想法

所以…它的工作。 这可能是反模式,错误或疯狂,但是…我想知道一个更好的select。

 let PromiseWaiter = function() { let promise = null; let thens = []; let self = this; this.setPromise = function (p) { promise = p; thens.forEach(t => { p.then(t); }); }; this.then = function(t) { if (promise === null) { thens.push(t); } else { promise.then(t); } return self; }; this.reset = function() { promise = null; thens = []; }; }; module.exports = PromiseWaiter; 

使用它:

 let waitForA = new PromiseWaiter(); let waitForB = new PromiseWaiter(); let waitForD = new PromiseWaiter(); socket.on('A', data => { waitForA.setPromise(asynchronousTaskForA()); }); socket.on('B', data => { waitForA.then(neededValue => { waitForB.setPromise(asynchronousTaskForB(neededValue)); }); }); socket.on('C', data => { waitForB.then(neededValue => { asynchronousTaskForC(neededValue); }); }); socket.on('D', data => { waitForB.then(neededValue => { waitForD.setPromise(asynchronousTaskForD(neededValue)); }); }); // Note: I am confused why these functions did not return a Promise before // They have always done that. function asynchronousTaskForA() { return new Promise((resolve, reject) => { // something resolve('something needed by B'); }); } function asynchronousTaskForB(value) { return new Promise((resolve, reject) => { // something with value resolve('something needed by C ... D'); }); } function asynchronousTaskForC(value) { return new Promise((resolve, reject) => { // something with value resolve(); }); } function asynchronousTaskForD(value) { return new Promise((resolve, reject) => { // something with value resolve('something needed by E ... F'); }); } 

谢谢!

如果promiseForA还没有定义呢?

只是不要asynchronous分配给它。 立即创build – 为它做出承诺。 哦,承诺的承诺只是一个承诺。

 const A = new Promise(resolve => socket.on('A', resolve)); const B = new Promise(resolve => socket.on('B', resolve)); const C = new Promise(resolve => socket.on('C', resolve)); const D = new Promise(resolve => socket.on('D', resolve)); const afterA = A.then(asynchronousTaskForA); const afterB = Promise.all([afterA, B]).then(asynchronousTaskForB); const afterC = Promise.all([afterB, C]).then(asynchronousTaskForC); const afterD = Promise.all([afterB, D]).then(asynchronousTaskForD); 

我的想法可能是反模式,错误或疯狂,但是…它的工作。

是啊。 我看到的问题是,它看起来非常像一个承诺(或推迟),但不是一个:

  • setPromise只是resolve
  • then注册callback,但不返回一个等待callback结果的承诺,所以不可链接
  • 承诺1不可能reset ,但我不确定是否真的需要这个。

正如我在评论中所说,最好不要推出自己的解决scheme,而只是使用Promise 。 当然,你可能会写一个辅助函数socket.getPromiseForNext('A')左右。

1:但是,您可以使用像Creed这样的支持取消的实现。 我怀疑刚刚创build一个等待下一个事件的新实例应该已经足够了。

你可以在callback的return语句中创build一个promise。 例:

 promiseA .then( data => { return new Promise((resolve, reject) => { // do some job }); }) 

就你使用节点而言,你可以使用async / await方法:

 async function startFlow() { // here you sure create promise, instead of promise A const res1 = await promiseA; // here you sure create promise, instead of promise B const res2 = await promiseB; // etc... } // Start your functions execution startFlow();