【问题标题】:typescript - while loop for promise打字稿 - 承诺的while循环
【发布时间】:2017-04-21 01:12:44
【问题描述】:

我有一个大数组,它被分成更小的块。然后我对每个块进行异步调用:

  myFunc(arrObjs: any[], chunkSize: number): Promise<any> {
    let result = Promise.resolve(); // To start the chain

    while(arrObjs.length) {
      // Extracting array chunk
      let chunk = arrObjs.splice(0, chunkSize);
      // Building the chain
      result = result.then(() => {
        return someAsynFunc(
          chunk
        );
      });
    }
    return result;
  }

在我的解决方案之上。我需要按顺序运行异步函数(系列承诺),所以我构建了一个承诺链。

有没有更好的方法来做到这一点?

【问题讨论】:

  • 如果您要等待上一个异步块处理完成后再开始下一个,那么首先执行所有这些异步的目的是什么?
  • 我无法控制异步函数,它本质上是异步的

标签: javascript loops typescript promise


【解决方案1】:

是的,您可以使用reduce 模式:

function myFunc(arrObjs: any[], chunkSize: number): Promise<any> {
    const chunks : any[] = [];
    while (arrObjs.length) {
        chunks.push(arrObjs.splice(0, chunkSize));
    }

    return chunks.reduce((p : Promise<any>, chunk : any[]) => {
        return p.then(() => someAsyncFunc(chunk));
    }, Promise.resolve());
  }

(我认为我的这些类型注释是正确的;如果没有,希望你能读过去...)

请注意,我保留了您实际上从 arrObjs 数组中删除数据的原始行为,但通常我不提倡像这样更改从调用者传递的对象。

这是一个例子:

function myFunc(arrObjs, chunkSize) {
  const chunks = [];
  while (arrObjs.length) {
    chunks.push(arrObjs.splice(0, chunkSize));
  }

  return chunks.reduce((p, chunk) => {
    return p.then(() => someAsyncFunc(chunk));
  }, Promise.resolve());
}

function someAsyncFunc(chunk) {
  console.log("Start handling", JSON.stringify(chunk));
  return new Promise(resolve => {
    setTimeout(() => {
      console.log("Done handling", JSON.stringify(chunk));
      resolve();
    }, 800);
  });
}

const array = [0, 1, 2, 4, 5, 6, 7, 8, 9];
myFunc(array, 3).then(() => {
  console.log("Done");
});

另请注意,上述内容会在处理它们时提前从数组中删除所有块。如果您想按处理它们(这会与使用该数组的其他任何东西产生串扰,可以添加/删除/等),您可以做很多相同的事情,只是没有reduce:

// Cross-talky version
function myFunc(arrObjs : any[], chunkSize : number) : Promise<any> {
  return new Promise<any>(function processChunk(resolve : function) {
    const chunk : any[] = arrObjs.splice(0, chunkSize);
    if (chunk.length == 0) {
      resolve();
    } else {
      someAsyncFunc(chunk).then(() => processChunk(resolve));
    }
  });
}

// Cross-talky version
function myFunc(arrObjs, chunkSize) {
  return new Promise(function processChunk(resolve) {
    const chunk = arrObjs.splice(0, chunkSize);
    if (chunk.length == 0) {
      resolve();
    } else {
      someAsyncFunc(chunk).then(() => processChunk(resolve));
    }
  });
}

function someAsyncFunc(chunk) {
  console.log("Start handling", JSON.stringify(chunk));
  return new Promise(resolve => {
    setTimeout(() => {
      console.log("Done handling", JSON.stringify(chunk));
      resolve();
    }, 800);
  });
}

const array = [0, 1, 2, 4, 5, 6, 7, 8, 9];
myFunc(array, 3).then(() => {
  console.log("Done");
});
setTimeout(() => {
  array.splice(2, 0, 'cross', 'talk');
}, 1000);

【讨论】:

  • 您的解决方案的内存使用情况如何?它将分块数组保存在内存中,直到完整的链被解析。
  • @user51713:通常这不是问题(您没有在问题中指出这是一个内存敏感的情况)。如果这是一个问题,你会想做其他事情(比如我后来添加的串扰版本)。
猜你喜欢
  • 2017-10-21
  • 2013-06-17
  • 2016-09-29
  • 1970-01-01
  • 1970-01-01
  • 2015-11-13
  • 2020-03-10
  • 2018-12-19
相关资源
最近更新 更多