等待承诺链有啥问题?
Posted
技术标签:
【中文标题】等待承诺链有啥问题?【英文标题】:What's wrong with awaiting a promise chain?等待承诺链有什么问题? 【发布时间】:2019-06-20 11:49:15 【问题描述】:我正在开发一个 Angular 6 应用程序,有人告诉我以下是反模式:
await someFunction().then(result =>
console.log(result);
);
我意识到等待一个承诺链是没有意义的。如果 someFunction() 返回一个 Promise,那么如果你在等待它,你就不需要 Promise 链。你可以这样做:
const result = await someFunction();
console.log(result);
但有人告诉我,等待承诺链可能会导致错误,或者它会破坏我的代码中的东西。如果上面的第一个代码 sn-p 与第二个 sn-p 执行相同的操作,那么使用哪个代码有什么关系。第一个 sn-p 引入了哪些危险而第二个没有?
【问题讨论】:
我认为***的“await someFunction()”是不可能的,它必须被包裹在一些异步函数中,或者不是? 【参考方案1】:在底层,异步/等待只是承诺。
也就是说,当你有一些看起来像这样的代码时:
const result = await myAsyncFunction();
console.log(result):
这和写的一模一样:
myAsyncFunction().then(data =>
const result = data;
console.log(result);
);
那么原因 - 你不应该混合 async/await 和 .then
链 - 是因为它令人困惑。
最好只选择一种风格并坚持下去。
当您选择一个时 - 您不妨选择 async/await - 它更容易理解。
【讨论】:
it's more understandable
这是 100% 的意见。我发现很难向某些人解释 async
函数实际上在第一个 await
表达式处返回给调用者。在我看来,仅 Promise 的学习曲线就比 async
/ await
要少。
其实我认为上面的第一个代码示例是错误的,因为没有***的await调用。它应该包裹在一些async function()块中,否则无法执行awai ,还是我错了?在我看来,这就是 async-await 的缺点......它有点开销恕我直言......【参考方案2】:
如果您的then
代码返回了一个承诺而不是调用console.log
,那么您的第一个示例将是await
,但您的第二个示例不会。
当您使用async/await
时,您将在try/catch
块中捕获您的拒绝。您的代码将更少嵌套和更清晰。
使用then
通常会导致更多的嵌套,并且更难阅读代码。
您可以await
任何东西,无论它是否返回promise
。有时,这种未来证明调用的方法可能有一天会变成异步的,或者只是返回一个承诺而不声明异步。
缺点是复杂性、性能和兼容性,与收益相比,所有这些都相形见绌。
我发现,如果您在调用函数后依赖于函数的返回值,并且它是或可能最终变为异步的,请使用await
装饰调用您的函数,让您高兴,无论它是当前异步还是返回承诺。
【讨论】:
为了解释一个引入错误的场景,+1。以不好的(不知道是否讽刺?)建议作为结论,-1。 我看不出这有什么讽刺意味。你是那些async/await
的仇恨者之一吗?我已经教了数百名学生使用它们,然后再也不会回去了。
So decorate your code with await to your heart's delight!
似乎非常暗示在不必要时使用它,尤其是与您之前的断言相结合时,您可以await
任何东西。那么,我应该var foo = await "bar";
仅仅因为它有效吗?也许有一天我会把那个字符串变成一个承诺?同时,我必须把它放在一个async
函数中,因为我想将一个随机的await
表达式粘贴到“面向未来”的东西上。是的,我很可笑,但是当我阅读您答案末尾的声明时,这听起来仍然像讽刺。
是的。如果函数返回一个定义then()
函数的对象,await
ing 它与return
ing 它完全不同。这确实是有害且不兼容的行为。
"foo() 是同步的,但有朝一日可能会变成异步的" - 这不是使用 await
的好理由,将其视为今天已经是异步的。函数是否异步是其 API 契约的重要组成部分,不能随意更改。记录你正在做的事情并坚持下去。【参考方案3】:
有人告诉我,等待承诺链会破坏我的代码。
不一定,你的两个代码 sn-ps 确实工作相同(只要someFunction()
真的返回一个承诺)。
使用哪一个有什么关系。第一个 sn-p 引入了哪些危险而第二个没有?
很难理解和维护,混合不同的风格会让人困惑。混乱导致错误。
考虑到您需要在console.log()
调用的位置添加另一个promise 调用,甚至是函数的条件返回。你能像在函数的其他地方一样在回调中使用await
吗,你需要return
来自then
回调的结果,甚至可以从外部函数中使用return
吗?所有这些问题甚至都不会出现在第一个 sn-p 中。虽然对于您的玩具示例可以很容易地回答它们,但在具有更复杂和嵌套控制流的实际代码中可能并不容易。
所以你应该更喜欢更简洁和干净的那个。坚持await
以获得一致性,避免then
在async function
s1。
1:当然,规则总有例外。我会说在某些情况下使用catch
或第二个then
回调,use promise chaining for error handling 会更干净。
【讨论】:
以上是关于等待承诺链有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章
承诺。 return resolve() 和 resolve() 有啥区别?
赋值运算符、映射和承诺。该代码有啥问题? Javascript