与"回调地狱" 等类似的替代方案相比,有很多方法可以通过ES2015承诺来实现良好的控制流程。那里有很多例子。
但是,当控制流中每个步骤的参数依赖于上一步的返回/已解决值时,更难找到一个好的语法。实际的用例通常有点复杂,因此简化的示例语法可能看起来不那么难看,但它使解释和讨论更容易。
所以,问题是 如何制作简单(易读且易于维护)但灵活的方法来解决此类案件。
控制流程中的三个操作。每个都是一个返回Promise
的函数。
function firstOperation(arg1) {
return new Promise(...);
}
function secondOperation(firstResponse) {
return new Promise(...);
}
function thirdOperation(firstResponse, secondResponse) {
return new Promise(...);
}
如果每一步都只依赖于前一步,它可能看起来像这样:
firstOperation('foo')
.then(res1 => secondOperation(res1))
.then(res2 => thirdOperation(res2));
甚至更简单:
firstOperation('foo')
.then(secondOperation)
.then(thirdOperation);
没问题。但在这种情况下,thirdOperation需要前两个操作的参数。
在ES8中,我猜这看起来像是:
const res1 = await firstOperation('foo');
const res2 = await secondOperation(res1);
const res3 = await thirdOperation(res1, res2);
我想使用已完成的标准,因此我希望通过ES2015语法或可能的promise / generator库为这类案例找到最佳解决方案。
可能(但不是非常简单/可读)的解决方法:
firstOperation('foo')
.then(res1 => secondOperation(res1)
.then(res2 => thirdOperation(res1, res2))
);
让它成为一种承诺地狱"这是有效的,但在更复杂的情况下(不止一个级别)会变得丑陋,难以阅读/维护。
另一种解决方案:
firstOperation('foo')
.then(res1 => secondOperation(res1)
.then(res2 => ({ res1, res2 })))
.then(({ res1, res2 }) => thirdOperation(res1, res2));
与前一个相比,唯一的好处是,如果有超过三个操作,它们都可以在同一级别上调用,而不是每次进一步缩进一个级别。并且在每次操作之后,结果将与其他操作合并为"上下文对象"保持所有结果。
所以,直到出现标准化方式(可能是ES8),我想使用某种承诺/生成器库是一种可接受的解决方案。我最希望的是,我不需要自己触摸功能。就像仍然让他们(示例中的firstOperation
,secondOperation
和thirdOperation
)以正常方式获取参数,并返回一个直接用值解析的promise,而不是将它们重写为能够适应不同的控制流程用例。
解决此类案件的建议?
答案 0 :(得分:2)
你可以这样做:
const res1 = firstOperation('foo');
const res2 = res1.then(secondOperation);
const res3 = Promise.all([res1, res2])
.then(args => thirdOperation(...args));
答案 1 :(得分:-1)
我通常在promise链之前声明变量并将结果存储在那里,所有调用都可以访问它们。它有效,不需要增加缩进/更深的练级,并且它不需要你改变你的功能参数。
let firstResponse;
firstOperation(userId)
.then(firstResp=>{
firstResponse = firstRestp;
return secondOperation(firstResponse);
})
.then(secondResponse=>{
return thirdOperation(firstResponse, secondResponse);
});
这个answer in the linked duplicate question指出了这种方法的一些缺点。例如,变量可能在填充之前使用。