[英]ECMAScript 2015 call Promises sequentially
我正在嘗試重寫同步聯結以與Promise一起使用,並且對此有些困惑。 我有一個函數,根據參數和結果調用不同的例程A
, B
和C
:
const worker = (v, r, ok, er)=>{
if(v > 10) {
ok(r)
} else {
er(r)
}
};
const A = v=>{let r = null; worker(v, 'a', _r=>r=_r, ()=>{});return r};
const B = v=>{let r = null; worker(v, 'b', _r=>r=_r, ()=>{});return r};
const C = v=>{let r = null; worker(v, 'c', _r=>r=_r, ()=>{});return r};
const mainSync = (obj)=>{
let result = null;
if(obj.a) {
result = A(obj.a);
}
if (!result && obj.b) {
result = B(obj.b);
}
if (!result && obj.c) {
result = C(obj.c);
}
return result;
}
使用同步A
, B
和C
可以正常工作https://repl.it/JcjE/0 :
mainSync({a:4}) === null;
mainSync({a:4, b:14}) === 'b';
mainSync({a:14, b:14}) === 'a';
mainSync({b:4, c:14}) === 'c';
// etc
現在, A
, B
和C
成為Promises:
const worker = (v, r, ok, er)=>{
if(v > 10) {
ok(r)
} else {
er(r)
}
};
const A = v=>new Promise((ok, er)=>worker(v, 'a', ok, er));
const B = v=>new Promise((ok, er)=>worker(v, 'b', ok, er));
const C = v=>new Promise((ok, er)=>worker(v, 'c', ok, er));
而且我不太確定如何處理它:
const mainAsync = (obj)=>{
// what todo here?
}
我對mainAsync很高興返回Promise本身,例如
mainAsync({a:4}).then(r=>r === null);
mainAsync({a:4, b:14}).then(r=>r === 'b');
mainAsync({a:14, b:14}).then(r=>r === 'a');
mainAsync({b:4, c:14}).then(r=>r === 'c');
問題是對B
調用取決於A
結果,對C
調用取決於A
和B
結果,並且還沒有async/await
可用。
我已經嘗試過我的幼稚方法https://repl.it/Jcjw/0,但是它很糟糕,並且無法在現實生活中發揮作用。
PS:如果可能,我正在尋找香草javascript,並且知道類似的問題,例如
等等,但不知道如何將它們應用於我的案子。
根據要嘗試定位的瀏覽器類型,可以確定使用chrome中的async/await
功能。
function promiseA(){return Promise.resolve(20)} function promiseB(arg){return Promise.resolve(arg * 2)} function promiseC(arg){return Promise.resolve(arg + 10)} (async function(){ let a = await promiseA(); console.log(a) let b = await promiseB(a); console.log(b) let c = await promiseC(b); console.log(c) })();
要依次調用promise,可以在.then
回調中調用下一個。 您的條件( if (!result && ...)
)很容易翻譯:
function mainAsync(obj) {
return (obj.a ? A(obj.a) : Promise.resolve())
.then(result => !result && obj.b ? B(obj.b) : result)
.then(result => !result && obj.c ? C(obj.c) : result);
}
如果您需要對許多屬性執行此操作,則可以通過使用查找表和循環(在這種情況下為Array#reduce
)來避免重復太多:
const funcs = {
a: A,
b: B,
c: C,
};
const props = ['a', 'b', 'c'];
function mainAsync(obj) {
return props.reduce(
(promise, prop) => promise.then(
result => !result && obj[prop] ? funcs[prop](obj[prop]) : result
).catch(() => Promise.resolve(null)),
Promise.resolve(null)
);
}
mainAsync = mainSync;
或更簡單:
function mainAsync({a,b,c}){
if(c) return C(c);
if(b) return B(b);
if(a) return A(a);
}
如果您希望在返回之前兌現所有承諾:
function mainAsync({a,b,c}){
var promises=[];
if(a) promises.push(A(a));
if(b) promises.push(B(b));
if(c) promises.push(C(c));
return Promise.all(promises).then(val=>val.pop())
}
mainAsync({a:1,b:2,c:3});
如果不選擇使用ES7編譯器(用於異步/等待),則可以使用ES2015 生成器實現異步控制流。 這是一個簡單的示例實現:
function *main() {
let a = yield Promise.resolve(5);
let b = yield Promise.resolve(a + 10);
let c = yield Promise.resolve(b + 15);
// place the rest of your code here
console.log(c); // prints 30
}
function execAsync(generator, previousValue) {
const nextValue = generator.next(previousValue);
if (!nextValue.done) {
let promise = nextValue.value;
// FIXME: promise rejection is not handled
promise.then(function (value) {
execAsync(generator, value);
});
}
}
// ...
// start the execution
execAsync(main());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.