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

问题描述 投票:3回答:2

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

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,而不是在等待()的情况下?

javascript node.js promise async-await generator
2个回答
3
投票

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

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

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


2
投票

可以调整第一个示例中的代码,以输出使用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)
© www.soinside.com 2019 - 2024. All rights reserved.