如何从异步迭代器产生承诺序列? [英] How do I yield a sequence of promises from an async iterator?

查看:68
本文介绍了如何从异步迭代器产生承诺序列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I start with a function which renders and yields a sequence of image blobs.

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

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

That works fine, but the performance isn't ideal because each promise has to be resolved before starting on the next operation. Instead, the caller should decide when to wait for the promises, while still preserving the order.

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运算符在异步函数中解压缩了Promise ,因此yield promise在功能上与yield await promise相同.

To my surprise, this fails to compile because "Type Blob is not assignable to type Promise<Blob>." Further inspection shows that the yield operator unpacks promises within an async function, such that yield promise is functionally identical to yield await promise.

为什么yield运算符以这种方式起作用?是否可以从异步迭代器产生承诺序列?

Why does the yield operator act this way? Is it possible to yield a sequence of promises from an async iterator?

推荐答案

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

For some reason these two statements seem to have the same effect :

yield await promise
yield promise

第一个语句实际上在Javascript中编译为yield yield __await(promise),可以按预期工作.我认为,您应该能够返回迭代元素或元素的Promise,因此await并不是必需的

The first statement actually compiles to yield yield __await(promise) in Javascript, which works as expected. I think the idea is that you should be able to return either an element of the iteration or a promise of an element, so the await is not really necessary

据我对异步迭代器规范的理解,应在以下情况下使用迭代本身是异步的,在您的情况下,迭代本身不是异步的,它更多是一种返回交互的异步方法.我会去的:

From my understanding of async iterator spec, it should be used in cases where the iteration itself is asynchronous, in your case the iteration itself is not asynchronous, it's more of an asynchronous method that returns an interation. I would go with:

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

OR

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

这篇关于如何从异步迭代器产生承诺序列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆