在等待时,未能同时解决的发电机产生的承诺

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在等待时,未能同时解决的发电机产生的承诺相关的知识,希望对你有一定的参考价值。

我正在使用生成器函数来模拟可迭代的任务队列:

function* taskQueue() {
    for(let i=0; i<10; i++) {
        yield new Promise((resolve) => {
            setTimeout(() => resolve(i), (11 - i)*1000)
        })
    }
}

超时应该导致promises以相反的顺序解决(假设所有都在同一时间开始),最长的完成时间为11秒。

迭代承诺,并使用Promise.then(),代码需要完成最长超时(11秒)的长度:

function then() {
    let q = taskQueue();
    for(i of q) {
        i.then(console.log)
    }
}

但是,如果我等待承诺,那么它们会按顺序解决,并且需要线性时间(66秒)才能完成:

async function awaiting() {
    let q = taskQueue();
    for(i of q) {
        let n = await i;
        console.log(n);
    }
}

看来这是因为在上一个解析之前,taskQueue没有产生下一个promise,因为如果我将它们推送到一个数组然后等待,那么代码将在11秒内执行:

async function awaiting2() {
    let q = taskQueue();
    let tasks = [];
    for(i of q) {
        tasks.push(i);
    }
    for(i of tasks) {
        let n = await i;
        console.log(n);
    }
}

那么为什么在then()的情况下同时解决promises,而不是在等待()的情况下?

答案

这是因为Promises自然是异步的,因为无论Promise处于什么状态(Pending,Resolved,Error),程序的其余部分都将继续执行。

通过使用async关键字,您告诉功能块等待使用await关键字指定的每个Promise等待Promise在继续执行之前解析,这使得该功能块同步。

通过在Promise上调用.then()方法,您将使Promise执行异步,但.then()将在它完成时被调用,无论您的程序中发生了什么。

另一答案

可以调整第一个示例中的代码,以输出使用asycn/await的代码在使用的模式中使用.next().then()的相同结果 递归 “一种恰好引用自身的非终止程序。” What are the boundaries of recursion?

function* taskQueue() {
  for (let i = 0; i < 10; i++) {
    yield new Promise((resolve) => {
      setTimeout(() => resolve(i), (11 - i) * 1000)
    })
  }
}

const queue = taskQueue();

const awaiting = ({value:promise, done}, q) => 
  done ? {done} : promise.then(data => (console.log(data), awaiting(q.next(), q)));

awaiting(queue.next(), queue)
.then(console.log)
.catch(console.error)

以上是关于在等待时,未能同时解决的发电机产生的承诺的主要内容,如果未能解决你的问题,请参考以下文章

等待但从未解决/拒绝承诺内存使用[重复]

在更新状态和重定向之前等待所有承诺解决

如何在 JS 中使用 try、catch、.then 链接和异步等待来解决承诺?

暂停功能,直到承诺解决[重复]

解决未能加载文件或程序集“Newtonsoft.Json ...."或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)(代码片段

等待内部带有承诺的 forEach 完成