Ben*_*Ben 15 javascript async-await
MDN说 for await...of有两个用例:
该
for await...of语句创建一个循环迭代异步可迭代对象以及同步可迭代对象,...
我以前知道前者:使用Symbol.asyncIterator. 但我现在对后者感兴趣:同步迭代。
以下代码迭代一个同步可迭代对象 - 一个 promise 数组。它似乎阻碍了每个承诺的实现。
async function asyncFunction() {
try {
const happy = new Promise((resolve)=>setTimeout(()=>resolve('happy'), 1000))
const sad = new Promise((_,reject)=>setTimeout(()=>reject('sad')))
const promises = [happy, sad]
for await(const item of promises) {
console.log(item)
}
} catch (err) {
console.log(`an error occurred:`, err)
}
}
asyncFunction() // "happy, an error occurred: sad" (printed in quick succession, after about 5 seconds)Run Code Online (Sandbox Code Playgroud)
根据下面显示的逻辑,这种行为似乎类似于依次等待每个承诺。这个说法正确吗?
async function asyncFunction() {
try {
const happy = new Promise((resolve)=>setTimeout(()=>resolve('happy'), 1000))
const sad = new Promise((_,reject)=>setTimeout(()=>reject('sad')))
const promises = [happy, sad]
for(let p of promises) {
const item = await p
console.log(item)
}
} catch (err) {
console.log(`an error occurred:`, err)
}
}
asyncFunction() // "happy, an error occurred: sad" (printed in quick succession, after about 5 seconds)Run Code Online (Sandbox Code Playgroud)
我问,因为这个代码模式有一个隐含的排斥线了陷阱是Promise.all和Promise.allSettled避免,这似乎很奇怪,我认为这种模式会被语言的明确支持。
window.addEventListener('unhandledrejection', () => {
console.log('unhandled rejection; `sad` was not being awaited at the time it rejected')
})
async function asyncFunction() {
try {
const happy = new Promise((resolve)=>setTimeout(()=>resolve('success'), 1000))
const sad = new Promise((_,reject)=>setTimeout(()=>reject('failure')))
const promises = [happy, sad]
for(let p of promises) {
const item = await p
console.log(item)
}
} catch (err) {
console.log(`an error occurred:`, err)
}
}
asyncFunction() // "unhandled rejection; `sad` was not being awaited at the time it rejected" (after about zero seconds), and then "happy, an error occurred: sad" (printed in quick succession, after about 5 seconds)Run Code Online (Sandbox Code Playgroud)
是的,这很奇怪,你不应该这样做。不要迭代承诺数组,它会导致您提到的 unhandled-rejections 问题。(另见这个更具体的解释。)
那么为什么该语言支持这一点呢?继续草率的 promise 语义。
您可以在讨论提案这一部分的问题的评论中找到确切的推理:
我认为我们应该回退,
Symbol.iterator因为我们当前的 Promise 语义都是关于允许将同步事物用作异步事物。你可以称之为“草率”。它遵循 上面@groundwater的逻辑,但我只想更详细地说明相似之处。的“链接”语义
.then都是关于此的。您可以从 Promise.then或标量值返回;全部都是一样。您调用Promise.resolve不是为了将某些东西包装在 Promise 中,而是将某些东西转换为 Promise——当您有某些东西或其他东西时获得一个异步值。的语义
async和await都是关于懒散为好。您可以await在异步函数中使用任何非 Promise 表达式,并且一切正常,方式完全相同,只是您将控制权交给作业队列。同样,你可以“防御性地”放置async任何你想要的东西,只要你await得到结果。如果你有一个返回 Promise 的函数——无论如何!你可以把它变成async函数,而且从用户的角度来看,没有任何变化(即使从技术上讲,你得到了一个不同的 Promise 对象)。异步迭代器和生成器应该以相同的方式工作。就像您可以等待一个意外地不是 Promise 的值一样,一个合理的用户希望能够
yield*在异步生成器中同步迭代器。for await如果用户以这种方式防御性地标记循环,认为他们可能会获得异步迭代器,则循环应该类似地“正常工作”。我认为打破所有这些相似之处将是一件大事。它会使异步迭代器不符合人体工程学。让我们下次在 TC39 上讨论异步生成器/迭代器时讨论这个问题。
| 归档时间: |
|
| 查看次数: |
1182 次 |
| 最近记录: |