如何从异步迭代器中产生一系列promise?

pie*_*dar 5 iterable async-await typescript

我从一个渲染并生成一系列图像斑点的函数开始.

async function* renderAll(): AsyncIterableIterator<Blob> {
  const canvases = await getCanvases();
  for (const canvas of canvases) {
    yield await new Promise<Blob>((resolve, reject) => {
      canvas.toBlob(result => { if (result) resolve(result); else reject(); });
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

这样可以正常工作,但性能并不理想,因为必须在开始下一个操作之前解决每个承诺.相反,调用者应该决定何时等待承诺,同时仍然保留订单.

async function* renderAll(): AsyncIterableIterator<Promise<Blob>> {
  const canvases = await getCanvases();
  for (const canvas of canvases) {
    yield new Promise<Blob>((resolve, reject) => {
      canvas.toBlob(result => { if (result) resolve(result); else reject(); });
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,这无法编译,因为"类型Blob不能分配给类型" Promise<Blob>.进一步检查表明,yield操作员在异步功能中解包承诺,这yield promise在功能上是相同的yield await promise.

为什么yield操作员这样做?是否有可能从异步迭代器中产生一系列promise?

Tit*_*mir 2

出于某种原因,这两个语句似乎具有相同的效果:

yield await promise
yield promise
Run Code Online (Sandbox Code Playgroud)

第一条语句实际上编译为yield yield __await(promise)Javascript,它按预期工作。我认为这个想法是你应该能够返回迭代的元素或元素的承诺,所以这await并不是真正必要的

根据我对异步迭代器规范的理解,它应该在迭代本身是异步的情况下使用,在您的情况下迭代本身不是异步的,它更多的是返回交互的异步方法。我会选择:

async function renderAll(): Promise<Iterable<Promise<IBlob>>> {
    const canvases = await getCanvases();
    return (function* () {
        for (const canvas of canvases) {
            yield new Promise<IBlob>((resolve, reject) => {
                canvas.toBlob(result => { if (result) resolve(result); else reject(); });
            });
        }
    })();
}
Run Code Online (Sandbox Code Playgroud)

或者

async function renderAll4(): Promise<Iterable<Promise<IBlob>>> {
    return (await getCanvases())
        .map(canvas => new Promise<IBlob>((resolve, reject) => {
                canvas.toBlob(result => { if (result) resolve(result); else reject(); });
            })
        );
}
Run Code Online (Sandbox Code Playgroud)