如何产生异步迭代器的一系列承诺



i从呈现并产生一系列图像斑点的函数开始。

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(); });
    });
  }
}

效果很好,但是性能并不理想,因为在开始下一个操作之前,必须解决每个诺言。相反,呼叫者应决定何时等待承诺,同时仍保留订单。

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(); });
    });
  }
}

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

为什么yield操作员以这种方式行动?是否可以从异步迭代器产生一系列承诺?

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

yield await promise
yield promise

第一个语句实际上在JavaScript中编译为yield yield __await(promise),该语句按预期工作。我认为您的想法是您应该能够返回迭代的元素或元素的承诺,因此await不是真正必要的

从我对异步迭代器规范的理解中,应在迭代本身异步的情况下使用它,在您的情况下,迭代本身不是异步,它更像是一种异步的方法,它返回了Intidation。我会选择:

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(); });
            });
        }
    })();
}

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(); });
            })
        );
}

要解决yield操作员的惊人行为,一种可能性是将承诺包裹在功能中。

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(); });
    });
  }
}

我不确定这是否是一个好习惯,但是它确实允许呼叫者安排异步工作。

最新更新