JavaScript与回调循环异步

时间:2018-07-02 04:30:57

标签: javascript node.js asynchronous ecmascript-6 es6-promise

我有一个棘手的情况,需要收集属于某些类型(给定数组中的类型)的键,然后过滤收集的键并传递给删除函数。

收集过程调用外壳程序代码,并在循环内的回调中处理结果。我将需要等到整个回调循环完成,然后传递给删除功能。

我在节点代码中使用shelljs,基本上如下所示:

var del_arr = [];

for (var i in types) {
  shell.exec(somecode with
    var [i], {
      silent: true
    },
    function(code, stdout, stderr) {
      somecode-processing/filtering stdout and pushes the results to del_arr;
    });
  //loop through array types[] and need to wait for all shell codes' callbacks to finish;
}

//then pass del_arr to deletion function

我无法在shelljs回调的这种格式下构建异步函数。我也不知道在这种情况下如何使用Promise。

您能告诉我如何实现这一非阻塞过程吗? 谢谢

4 个答案:

答案 0 :(得分:2)

child_process.exec变成一个承诺:

function execWrapper(command, options) {
  return new Promise((resolve, reject) => {
     shell.exec(command, options, (error, out, err) => {
       if (error) return reject(error);
       resolve({out: out, err: err});
     })
  })
}

然后,您可以遍历类型并将每个类型映射到一个Promise:

const promises = types.map(type => execWrapper(type, {slient: true}));

现在等待每个诺言解决,或等待一个诺言:

Promise.all(promises).then((del_arr) => {
  // del_arr is now a array of objects with the stdout and stderr of each type.
  // 
})

答案 1 :(得分:1)

这种情况的良好实现:

async function myAsyncFunction() {
  const promises = types.map((type) => myAsyncRequest(type));
  let del_arr = Promise.all(promises);
}

一篇很好的文章对此进行了解释:

https://medium.freecodecamp.org/avoiding-the-async-await-hell-c77a0fb71c4c

答案 2 :(得分:0)

尝试像

一样将shell.exec转换为Promise。
function shellPromise(command,option) {
  return Promise((resolv,reject)=>{
      shell.exec(command,option,(code,stdout,stderr)=>
            resolv({code:code,stdout:stdout,stderr:stderr})
      );
   };
};

然后您可以使用

之类的东西
for (var i in types){
    var result=await shellPromise(somecode with var[i], {silent:true});
    // somecode-processing/filtering stdout and pushes the results to del_arr;
}

答案 3 :(得分:0)

您还可以在npm中使用async软件包。它提供的功能eachSeries可能会在您遇到的情况中派上用场,而无需使用promise和仅处理回调。

async.eachSeries(hugeArray, function iteratee(item, callback) {
    if (inCache(item)) {
        callback(null, cache[item]); // if many items are cached, you'll overflow
    } else {
        doSomeIO(item, callback);
    }
}, function done() {
    //...
});

有关如何使用此功能的更多详细信息:https://caolan.github.io/async/