Typescript 如何从异步迭代器生成一系列承诺?

Typescript 如何从异步迭代器生成一系列承诺?,typescript,async-await,iterable,Typescript,Async Await,Iterable,我从一个函数开始,该函数渲染并生成一系列图像斑点 async function* renderAll(): AsyncIterableIterator<Blob> { const canvases = await getCanvases(); for (const canvas of canvases) { yield await new Promise<Blob>((resolve, reject) => { canvas.toBlob

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

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函数*renderal():asynciiterableiterator{
const canvases=等待getCanvases();
用于(画布的const画布){
收益等待新承诺((决定、拒绝)=>{
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(); });
    });
  }
}
async函数*renderal():asynciiterableiterator{
const canvases=等待getCanvases();
用于(画布的const画布){
产生新的承诺((决定、拒绝)=>{
toBlob(result=>{if(result)resolve(result);else reject();});
});
}
}
令我惊讶的是,这无法编译,因为“Type
Blob
不可分配给Type
Promise
”进一步检查表明
yield
操作符在异步函数中解压承诺,因此
yield Promise
在功能上与
yield wait Promise
相同


为什么
产生
操作符会这样做?有可能从异步迭代器生成一系列承诺吗?

要解决
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(); });
    });
  }
}
async函数*renderal():AsyncIterableIterator承诺>{
const canvases=等待getCanvases();
用于(画布的const画布){
收益率()=>新承诺((解决、拒绝)=>{
toBlob(result=>{if(result)resolve(result);else reject();});
});
}
}

我不确定这是否是一种好的做法,但它确实允许调用者安排异步工作。

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

yield await promise
yield promise
第一条语句实际上编译成Javascript中的
yield\uuu-await(promise)
,正如预期的那样工作。我认为这个想法是,您应该能够返回迭代的元素或元素的承诺,因此
await
并不是真正必要的

根据我对spec的理解,它应该用于迭代本身是异步的情况,在您的情况下,迭代本身不是异步的,它更像是一种返回迭代的异步方法。我同意:

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(); });
            });
        }
    })();
}
异步函数renderAll():Promise{ const canvases=等待getCanvases(); 返回(函数*(){ 用于(画布的const画布){ 产生新的承诺((决定、拒绝)=>{ toBlob(result=>{if(result)resolve(result);else reject();}); }); } })(); }

异步函数renderAll4():Promise{ 返回(等待getCanvases()) .map(画布=>新承诺((解决、拒绝)=>{ 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(); });
            })
        );
}