async.mapLimit with Promise

倾然丶 夕夏残阳落幕 提交于 2020-08-10 23:43:05

问题


I'm trying to use the async module (v3) and especially the async.mapLimit method to submit a limited number of parallel asnychronous requests. This works well with callbacks in the following (simplified) sample code:

async = require('async');
async.mapLimit(['1','2','3','4','5'], 3, function(num, callback){
setTimeout(function(){
    num = num * 2,
    console.log(num);
    callback(null, num);
}, 
4000);  
},function(err, results){
    console.log(results);
});

As result I get the single values and finally the array with all values in 'results':

[2,4,6,8,10]

Now what I'm struggling with is to use the Promise based version of this method. The documentation says it returns a Promise if I don't supply a callback. How can I change this callback-based code into using Promises?

I tried e.g. this, but it only shows the first set of requests (this is updated after the first suggestions in the comments):

let numPromise = async.mapLimit(['1','2','3','4','5'], 3, function(num, callback){
    setTimeout(function(){
        num = num * 2,
        console.log(num);
        callback(null, num);
    }, 
    4000); 
});
Promise.all([numPromise]) //always calls .then immediately, without result
.then((result) => console.log("success:" + result))
.catch(() => console.log("no success"));

I do get back all single values correctly, but the '.then' executes immediately and gives me 'Success' with an empty 'result' variable.

Note: I have seen this thread ES6 Promise replacement of async.eachLimit / async.mapLimit of course, but I don't think that answers my question.

PS: I have found other solutions to this problem already, but I am really interested in how to use this module properly (with short, clean code).


回答1:


Here's the probably better answer, though the other alternative seemed fine as well:

const async = require('async');
const delay = require('util').promisify(setTimeout);
const numPromise = async.mapLimit(['1','2','3','4','5'], 3, async num => delay(200).then(() => num*2))
// or const numPromise = async.mapLimit(['1','2','3','4','5'], 3, async num => {
//    await delay(200);
//    return num*2;
// })
numPromise.then(console.log)
// or numPromise.then((results) => console.log(results))

Please also see this issue thread on GitHub as reference: GitHub: async.mapLimit does not return a Promise

I believe the issue with my code was in the iteratee function - either initially it wasn't asynchronous or using 'callback' instead of 'return' I assume (or maybe both ;-) ).




回答2:


The solutions was astonishingly simple - while I still believe the code above should be working (according to documentation), I found that there is another package that was built to work with promises: 'promise-async'

So I replaced the line

async = require('async');

with

async = require('promise-async');

and now the code above is working as expected:

let numPromise = async.mapLimit(['1','2','3','4','5'], 3, function(num, callback){
    setTimeout(function(){
        num = num * 2,
        console.log(num);
        callback(null, num);
    }, 
    4000);
})
//Promise.all([numPromise]) //Promise.all is not needed
numPromise
.then((result) => console.log("success:" + result))
.catch(() => console.log("no success"));

Returns

2
4
6
8
10
success:2,4,6,8,10


来源:https://stackoverflow.com/questions/57622495/async-maplimit-with-promise

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!