我正在收听用户事件,其中一些取决于其他人的完成情况。处理这些事件是异步任务,因此我使用承诺。
让我说我得到了这个:
A
-> B
-> C
-> ...
-> D
-> E
-> ...
-> F
我最初的做法是保存A
的承诺,并使用B
的 then
方法附加A
的处理诺言。 B
和C
... D
和D
以及E
... F
也是如此。
但这些事件几乎可以在同一时间发生, B
可能会在A
之前发生。由于我无法听取尚未存在的承诺 ......您如何解决这个问题?
我的想法是为每个级别(A,B,D)定义一个对象,我可以附加一个承诺和处理未来事件即可。附加承诺时,我会迭代处理未来事件并将其设置为承诺then
。附加未来事件时,我会查看是否有承诺,并将其附加到then
或将其保存到数组或其他内容中。
您是否知道现有的解决方案已经解决了这个问题,或者我是否应该遵循我的想法?
谢谢。
我正在收听客户端的多媒体事件,这些事件通过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');
}
所以......它有效。它可能是反模式,错误或疯狂,但......我想知道一个更好的选择。
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');
});
}
谢谢!
答案 0 :(得分:2)
如果尚未定义
promiseForA
该怎么办?
不要异步分配给它。立即创建它 - 为它做出承诺。哦,对承诺的承诺只是一种承诺。
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
确实注册了回调,但没有返回等待回调结果的承诺,因此无法链接reset
,但我不确定你是否真的需要这个。正如我在评论中所说,最好不要推出自己的解决方案,只需使用Promise
即可。当然,您可以编写辅助函数socket.getPromiseForNext('A')
左右。
1:但您可以使用支持取消的Creed之类的实现。我怀疑只是创建一个等待下一个事件的新实例应该足够了。
答案 1 :(得分:0)
您可以在then
回调的return语句中创建一个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();