简体   繁体   English

Javascript异步调用链接

[英]Javascript asynchronous calls chaining

Given an array which contains objects of type A and B, where B can be transformed to a set of A type objects, via an asynchronous call, which would be the best way of transforming the array into an all A objects array (transforming each B object in a set of corresponding A objects) and execute a callback when Bs are transformed? 给定一个包含A和B类型对象的数组,其中B可以通过异步调用转换为一组A类型对象,这将是将数组转换为全A对象数组的最佳方法(转换每个B对象在一组相应的A对象中)并在转换Bs时执行回调?

    list = [A, B, A, B, A, A, B, A];

    function transform (B, callback) {
       //transform B type object into A type objects array [A, A, A].....
       callback([A, A, A]);
    }

    transformBObjectsIntoAObjects(list, callback) {
       // ?????????
      callback(list); // this should only be A type objects
    }

Well, you need to execute your final callbacks after all the callbacks from transformBtoList have returned a result. 好吧,你需要在transformBtoList所有回调都返回结果后执行你的最终回调。 There are multiple ways to do it: 有多种方法可以做到:

  1. Count how many callbacks you have passed away and decrement when they call back, and you know that you're finished when the counter has reached zero again. 计算你已经过去的回调数量,并在他们回电时递减,你知道当计数器再次达到零时你就完成了。

    However, this is cumbersome, and there are libraries that help you with it: 但是,这很麻烦,有些库可以帮助您:

  2. async.js is well-known and easy to use: async.js众所周知且易于使用:

     function transform(B, callback) { … } function transformBObjectsIntoAObjects(list, callback) { async.map(list, function(X, cb) { if (X is B) transform(X, cb) else cb([X]) }, function(results) { callback(concat(results)) } } 
  3. Promises (there are many implementations are a superior approach. They might be a bit more complex to understand, but have very nice properties and lead to nice & concise syntax. In your case, it would be Promises(有许多实现是一种更好的方法。它们可能会更复杂一些,但是具有非常好的属性并且会产生简洁明了的语法。在你的情况下,它会是

     function transform(B) { // no callback! // async: resolve([A, A, A]); // see docs of your promise library return promise; // for exact reference } function transformBObjectsIntoAObjects(list) { return Promise.all(list.map(function(X) { return (X is B) ? transform(X) : Promise.resolve([X]); })).then(concat); } 

Here is a complete working example with async: 这是一个完整的异步工作示例:

var async = require("async")

function A (id) {
  this.id = 'A' + id;
}

function B (id) {
  this.id = 'B' + id;
}

var list = [new A(1), new B(2), new A(3), new B(4)];

function transformBObjectsIntoAObjects (b, callback) {
   var ar = [], count = Math.random() * 5;
   for (var i = 1; i <= count; i++)
     ar.push(new A(b.id + "_" + i))
   return callback(null, ar);
}

async.map(list, function(arItem, cb) {

  return (arItem.constructor === B) ? transformBObjectsIntoAObjects(arItem, cb) : cb(null, arItem)

  }, function (err, arResult) {
    var flatAr = [].concat.apply([], arResult);
    console.log(flatAr);
  }
)

One such result (B parts are randomly generated) looks like: 一个这样的结果(B部分是随机生成的)看起来像:

[ { id: 'A1' }, { id: 'AB2_1' }, { id: 'AB2_2' }, { id: 'A3' }, { id: 'AB4_1' } ] [{id:'A1'},{id:'AB2_1'},{id:'AB2_2'},{id:'A3'},{id:'AB4_1'}]

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

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