如何启用 async.mapLimit 以使用 TypeScript async / await

How to enable async.mapLimit to work with TypeScript async / await

是否可以在 TypeScript 2.2x 中使用 Async NPM moduleasync/await 一起工作?

目标: 使用 Async 的 mapLimit function.

创建一个 10 个并行 HTTP 请求的网络抓取工具

包装的 HTTP 函数的示例如下:

async callUniRest(url: string): Promise<number> {
  return new Promise<number>(resolve => {
    unirest.get(url)
      .end((response: any) => {
          resolve(cheerio.load(response.body);
      });
    });
}

问题:

当我运行:

const myList: string[] = ['http...', 'http...', 'http...', 'http...']
async.mapLimit(myList, 10, callUniRest, function(err: any, results: any {
  console.log(results);
})

只有在第一个元素完成后才会调用回调。

问题: 如何启用 async.mapLimit 以处理多个呼叫?

没有。 async 模块为不能或不会使用 Promises 的人提供实用程序和抽象。他们不混。

更不用说,当您 myList 时,所有请求都已发送。

async.mapLimit 仅适用于接受回调的函数,不适用于 return Promise 的函数。

您可能想要使用 Bluebird 的 Promise.map() with the concurrency operator

Is it possible to use the 'async' npm module to work with async / await in Typescript

是的。

我发现 mapLimit 只是为第一组调用迭代器。这是因为我是从 TypeScript 转译过来的。如果我将本机 async/await 与 JS 一起使用,那么它就可以工作。这是因为,引用自async docs for AsyncFunction:

due to JavaScript limitations, we can only detect native async functions and not transpilied implementations.

因此,如果您使用异步库中的 asyncify 包装迭代器,那么您可以从迭代器内部 return 而不是使用回调:

If you are using async functions through a transpiler (e.g. Babel), you must still wrap the function with asyncify, because the async function will be compiled to an ordinary function that returns a promise.

这是一个有点人为的 TypeScript 示例,演示了如何执行此操作。注意:如果您删除 asyncify 调用,它将不起作用:

import { asyncify, mapLimit } from "async";

const listOfThings = "abcdefghijklmnopqrstuvwxyz".split("");

const convertToUppercase = async () =>
  await mapLimit<string, string[]>(
    listOfThings,
    5,
    asyncify(async letter => letter.toUpperCase())
  );

const init = async () => {
  const uppered = await convertToUppercase();

  console.log("done", uppered);
};

init();