简体   繁体   English

JavaScript与回调循环异步

[英]JavaScript async in a loop with callbacks

I have a tricky situation that needs to collect keys that belongs to certain types (types in a given array), then filter the collected keys and pass to a deletion function. 我有一个棘手的情况,需要收集属于某些类型(给定数组中的类型)的键,然后过滤收集的键并传递给删除函数。

The collection process calls shell codes and process the results in a callback within a loop. 收集过程调用外壳程序代码,并在循环内的回调中处理结果。 I will need to wait until the whole loop of callback finishes then pass to the deletion function. 我将需要等到整个回调循环完成,然后再传递给删除函数。

I am using shelljs in the node codes, basically look like the below: 我在节点代码中使用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

I wasn't able to build a async function in this format b/s of the shelljs callback. 我无法使用shelljs回调的这种格式b / s构建异步函数。 I also don't know how to use promise in this situation. 我也不知道在这种情况下如何使用Promise。

Can you tell me how to achieve this non-blocking process? 您能告诉我如何实现这一非阻塞过程吗? Thanks 谢谢

Turn child_process.exec into a promise: 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});
     })
  })
}

Then you can iterate over types and map each one to a promise: 然后,您可以遍历类型并将每个类型映射到一个Promise:

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

Now wait for each promise to resolve, or for one to reject: 现在,等待每个诺言得以解决,或者一个诺言被拒绝:

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

A good implementation of this case : 这种情况的良好实现:

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

A good article that explains this : 一篇很好的文章解释了这一点:

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

Try to convert shell.exec to Promise like 尝试将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})
      );
   };
};

Then you can use something like 然后,您可以使用类似

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;
}

You can also use async package in npm. 您还可以在npm中使用async包。 It provides a function eachSeries that might come handy in your situation, without useing promises and dealing with callbacks only. 它提供了一个eachSeries函数,在您的情况下可能会派上用场,而无需使用promises且仅处理回调。

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() {
    //...
});

For more details on how to use this function: https://caolan.github.io/async/ 有关如何使用此功能的更多详细信息: https : //caolan.github.io/async/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM