如何从头开始在Javascript中编写asynchronousMap函数?

我需要从头开始写这个asyncMap函数的帮助。 我想我已经差不多了,但我不确定为什么我一直得到错误的答案。 这是我迄今为止的代码:

function wait3For1(callback){ setTimeout(function(){ callback('one') }, 300) } function wait2For5(callback){ setTimeout(function(){ callback('five') }, 200) } function asyncMap(tasks, callback){ return callback( tasks.map((item) => item((element) => element))) } asyncMap([wait3For1, wait2For5], function(arr){ console.log(arr) //expect ['one', 'five'] }); 

我一直越来越[undefined, undefined]我敢肯定,这是因为我没有正确执行callbackwait2For5和wait3For1,但不知道是什么问题。

提前致谢!

问题是,你不等待结果回来,收集他们,然后通过callback发回他们。 看看这段代码是否有帮助。 (在您的程序中进行testing时,它可以工作。)

 function asyncMap(tasks, callback) { // array to collect the results let results = []; // count of how many results we're waiting for let remaining = tasks.length; tasks.forEach((task, i) => { task((result) => { // Store the result in the right position. results[i] = result; // See how many results we're still waiting for. remaining -= 1; // If we're done, invoke the callback. if (remaining === 0) { callback(results); } }); }); } 

在你的代码中,你正在使用同步的Array.prototype.map

 function asyncMap(tasks, callback){ return callback( tasks.map((item) => item((element) => element))) } 

由于wait3For1wait2For5没有return ,因此它们将隐式地返回undefined ,这将在.map调用的结果中使用。 很明显,我们希望在将映射值赋给最终结果之前等待callback被调用。

另一个问题是映射到一个数组使用一个函数map(items)没有真正的意义,没有一个函数来映射的项目。 所以我们也会在下面的解决scheme中解决这个问题。

如果您从asyncReduce开始,然后将asyncReduce实现为asynchronousreduce,将会有所帮助。 请注意,下面的代码将处理一系列的项目。 如果您希望并行处理项目,则需要稍微不同的方法。 让我知道在评论中,我会很乐意写出另一个变种。

 function wait3For1(callback){ setTimeout(function(){ callback('one') }, 300) } function wait2For5(callback){ setTimeout(function(){ callback('five') }, 200) } function asyncReduce(xs, f, initial, callback) { if (xs.length === 0) callback(null, initial) else f(initial, xs[0], function(x) { asyncReduce(xs.slice(1), f, x, callback) }) } function asyncMap(xs, f, callback) { asyncReduce(xs, function(acc, x, k) { f(x, function(y) { k(acc.concat([y])) }) }, [], callback) } asyncMap([wait3For1, wait2For5], function(f,callback) { f(callback) }, function(err, arr) { console.log(arr) //=> ['one', 'five'] }) 

你基本上是在创造可怜的人的承诺,但没有任何error handling能力。

尝试

  function waitFor(val, dur){ return new Promise(function(resolve, reject) { setTimeout(function() { resolve(val) }, dur); }); } Promise.all([waitFor('one',600), waitFor('five', 100)]).then( function(arr) { console.log(arr) //expect ['one', 'five'] }).catch(function(err){ console.log('ooops error:' , err) });