异步和高效的有序排序使用promise / deferred同步方法

时间:2017-05-07 07:49:41

标签: javascript jquery

我正在开发一个项目,使用API​​收集数据,然后绘制html来表示数据;有3种异步方法用于收集数据,当然还有相关的同步方法来为每种方法绘制html。

我希望在这里得到回复以帮助我确保我正在有效地完成这项工作 - 我将展示的代码工作,因此我的项目不会受到与此代码相关的任何问题的影响,但我不确定它的功效。

对于3个异步方法 - 让我们将它们称为async1,async2,async3(或者尊重地截断为a1,a2,a3) - 假设如下:

每个异步返回一个对象数组;然后对a2和a3迭代a1的结果,并将每个异步的所有结果推送到它们自己的'master'数组;然后迭代生成的数组以使同步方法将html内容绘制到页面,这样每个a1对象都有自己的容器,其中是来自a2的相关对象的容器,其中是来自a3的相关对象的容器。 / p>

这是我所拥有的伪代码表示(假设所有这些都包含在一个函数中):

//establish master arrays for each async method result
var a1array = [], a2array = [], a3array = [];

//establish Deferreds for each async master array, html
var a1arrDfd = $.Deferred(), a1htmlDfd = $.Deferred();
var a2arrDfd = $.Deferred(), a2htmlDfd = $.Deferred();
var a3arrDfd = $.Deferred(), a3htmlDfd = $.Deferred();

//get a1 data
async1(params).done(fn(a1data) {

  //iterate over a1 return and push to a1 master array
  var i, ilen = a1data.length, idone = 0;
  for (i = 0; i < ilen; i++) {
    a1array.push(a1data[i]);
    idone++;

    //if at last iteration of a1data array,
    //a1's master array is complete
    if (idone === ilen) { a1arrDfd.resolve(); }
  }
}).done(fn(a1data) {
  var j, jlen = a1data.length, jdone = 0;

  //loop thru a1data array to get a2 data and
  //push a2data to a2 master array
  for (j = 0; j < jlen; j++) {
    async2(param + a1data[j].key + param).done(fn(a2data) {
      var k, klen = a2data.length, kdone = 0;
      jdone++;

      //loop thru a2data array to push to a2 master array
      for (k = 0; k < klen; k++) {
        a2array.push(a2data[k]);
        kdone++;

        //if at last a1data iteration and a2data iterant,
        //a2's master array is complete
        if (jdone === jlen && kdone === klen) { a2arrDfd.resolve(); }
      }
    });
  }
}).done(fn(a1data) {
  var l, llen = a1data.length, ldone = 0;

  //loop thru a1data array to get a3 data and
  //push a3data to a3 master array
  for (l = 0; l < llen; l++) {
    async3(param + a1data[l].key + param).done(fn(a3data) {
      var m, mlen = a3data.length, mdone = 0;
      ldone++;

      //loop thru a3data array to push to a3 master array
      for (m = 0; m < mlen; m++) {
        a3array.push(a3data[m]);
        mdone++;

        //if at last a1data iteration and a3data iterant
        //a3's master array is complete
        if (ldone === llen && mdone === mlen) { a3arrDfd.resolve(); }
      }
    });
  }
});

//listen for completion of async1array, then
//paint html containers for each object in async1 array
$.when(a1arrDfd).done(fn() {
  var n, nlen = a1array.length, ndone = 0;
  for (n = 0; n < nlen; n++) {
    a1paintHtml;
    ndone++;

    //if at last a1array iteration,
    //a1's html painting is complete
    if (ndone === nlen) { a1htmlDfd.resolve(); }
  }
});

//listen for completion of async1 html containers and
//async2 array, then paint containers for
//each object in async2 array
$.when(a1htmlDfd, a2arrDfd).done(fn() {
  var o, olen = a2array.length, odone = 0;
  for (o = 0; o < olen; o++) {
    a2paintHtml;
    odone++;

    //if at last a2array iteration,
    //a2's html painting is complete
    if (odone === olen) { a2htmlDfd.resolve(); }
  }
});

//listen for completion of async2 html containers and
//async3 array, then paint containers for
//each object in async3 array
$.when(a2htmlDfd, a3arrDfd).done(fn() {
  var p, plen = a3array.length, pdone = 0;
  for (p = 0; p < plen; p++) {
    a3paintHtml;
    pdone++;

    //if at last a3array iteration,
    //a3's html painting is complete
    if (pdone === plen) { a3htmlDfd.resolve(); }
  }
});

注意:如果您倾向于使用setTimeout回复,请提供一个解释为什么 - IMO,使用setTimeout方法似乎是任意的,特别是在考虑如何确定使用什么作为延迟参数时,所以你有教育我在这方面的假设是不正确的。

提前感谢任何建议

1 个答案:

答案 0 :(得分:2)

经过近2个月的离去之后,我重新审视了这个项目,掌握了关于JS中Promises的更多知识,现在有以下内容摆脱了延迟反模式:

const a1array = [], a2array = [], a3array = [];

const a1get = async1(params).then(data => {
  a1array.push(...data);
  return a1array;
})

const a2get = a1get.then(a1data =>
  Promise.all(a1data.map(a1 =>
    async2(param + a1.key + param)
      .then(data => a2array.push(...data)))));

const a3get = a1get.then(a1data =>
  Promise.all(a1data.map(a1 =>
    async3(param + a1.key + param)
      .then(data => a3array.push(...data)))));

Promise.all([a1get, a2get, a3get]).then(() => {
  a1paintHtml();
  a2paintHtml();
  a3paintHtml();
});