使用Q.js顺序返回循环GET请求

时间:2016-03-24 01:17:48

标签: javascript node.js asynchronous q deferred

我的主要功能如下:

function main(body) {
    var deferred = Q.defer();
    // Make an API request
    console.log("body :"+ body);

    var jsonbody = JSON.parse(body);
    partialSequence = jsonbody['partialSequence'];
    uniqID =  jsonbody['uniq'];
    resultLength = jsonbody['resultLength'];

    console.log("resultLength :"+ resultLength);

    if (partialSequence.indexOf("G") > -1) ns.push("G");
    if (partialSequence.indexOf("A") > -1) ns.push("A");
    if (partialSequence.indexOf("C") > -1) ns.push("C");
    if (partialSequence.indexOf("T") > -1) ns.push("T");

    uniq = uniqID;
    var sequence = Promise.resolve();

    for (var i = 0; i < resultLength; i++) {
      location = i;
      for (var j = 0; j < nuclides.length; j++) {

        n = nuclides[j]

        var promise = getLocation(n, location, uniq);
        promise.then(function(values) {
          console.log("location :"+values[0] + " "+ values[1]);
          if (expressed) {
            isExpressed = true;
            if(route > 0) {
              for (var key in resultSeq) {
                if (resultSeq.hasOwnProperty(key)) {
                  var temp = resultSeq[key]
                  delete resultSeq[key];
                  temp = temp.concat(n);
                  resultSeq[temp] = temp;
                }
              }
            } else {
              resultSeq[n] = n;
            }
          }
        });
      }
      if (isExpressed) route++; //used to check if we append to existing sequences.
    }
    deferred.resolve();
    return deferred.promise
}

function getLocation(n, location, uniq) {
  var expressed
  var deferred = Q.defer();
  Q.ninvoke(request, 'get', {
    url:         "https://myapi.com/location?"+"location="+location+"&"+"nucleotide="+n+"&"+"uniq=    "+uniq
  }).spread(function(response, body) {
    expressed=1;
    var jsonbody = JSON.parse(body);
    return [jsonbody["expressed"], location];
  });

  return deferred.promise
}

当我在console.log中时,位置values[0]出现故障时应该是0,1,2 ....... n。我怎样才能做到这一点?非常感谢!

1 个答案:

答案 0 :(得分:0)

首先,让我们通过将代码放入一个传递位置索引的函数来简化内部for循环,然后在代码完成时返回一个新的promise。由于您只是处理数组的内容,因此可以使用.reduce()设计模式为每个数组元素链接一个promise。这将连续执行所有这些:

function innerWork(locationIndex) {
    // process the nuclides array for a given locationIndex
    return nuclides.reduce(function (p, n) {
        return p.then(function () {
            // now process a single locationIndex
            return getLocation(n, locationIndex, uniq).then(function (values) {
                console.log("location :" + values[0] + " " + values[1]);
                if (expressed) {
                    isExpressed = true;
                    if (route > 0) {
                        for (var key in resultSeq) {
                            if (resultSeq.hasOwnProperty(key)) {
                                var temp = resultSeq[key]
                                delete resultSeq[key];
                                temp = temp.concat(n);
                                resultSeq[temp] = temp;
                            }
                        }
                    } else {
                        resultSeq[n] = n;
                    }
                }
            });
        });
    }, Promise.resolve());
}

然后,可以通过手动链接到单个promise来完成外部循环:

var sequence = Promise.resolve();
for (var i = 0; i < resultLength; i++) {
    (function(index) {
        sequence = sequence.then(function() {
            return innerWork(index);
        });
    })(i);
}

这使用内部IIFE来捕获闭包中的循环索引,因此当innerWork(index)函数调用稍后作为promises链并及时执行时,我们有正确的值。

这样做是建立一系列承诺,这些承诺全部链接在一起然后从前面开始并一个接一个地执行。

总而言之,你最终得到了这个:

function main(body) {
    // Make an API request
    console.log("body :" + body);

    var jsonbody = JSON.parse(body);
    partialSequence = jsonbody['partialSequence'];
    uniqID = jsonbody['uniq'];
    resultLength = jsonbody['resultLength'];

    console.log("resultLength :" + resultLength);

    if (partialSequence.indexOf("G") > -1) ns.push("G");
    if (partialSequence.indexOf("A") > -1) ns.push("A");
    if (partialSequence.indexOf("C") > -1) ns.push("C");
    if (partialSequence.indexOf("T") > -1) ns.push("T");

    uniq = uniqID;

    function innerWork(locationIndex) {
        // process the nuclides array for a given locationIndex
        return nuclides.reduce(function (p, n) {
            return p.then(function () {
                // now process a single locationIndex
                return getLocation(n, locationIndex, uniq).then(function (values) {
                    console.log("location :" + values[0] + " " + values[1]);
                    if (expressed) {
                        isExpressed = true;
                        if (route > 0) {
                            for (var key in resultSeq) {
                                if (resultSeq.hasOwnProperty(key)) {
                                    var temp = resultSeq[key]
                                    delete resultSeq[key];
                                    temp = temp.concat(n);
                                    resultSeq[temp] = temp;
                                }
                            }
                        } else {
                            resultSeq[n] = n;
                        }
                    }
                });
            });
        }, Promise.resolve());
    }

    var sequence = Promise.resolve();
    for (var i = 0; i < resultLength; i++) {
        (function (index) {
            sequence = sequence.then(function () {
                return innerWork(index);
            });
        })();
    }
    if (isExpressed) route++; //used to check if we append to existing sequences.
    return sequence;
}

此外,请记住您的其他问题/答案中改进的getLocation()功能:

function getLocation(n, location, uniq) {
  var expressed
  return Q.ninvoke(request, 'get', {
    url:         "https://myapi.com/location?"+"location="+location+"&"+"nucleotide="+n+"&"+"uniq=    "+uniq
  }).spread(function(response, body) {
    expressed = 1;
    var jsonbody = JSON.parse(body);
    return [jsonbody["expressed"], location];
  });
}    

P.S。,您的原始代码有几个您引用的未声明变量。请确保在适当的范围内声明所有变量。例如,我不知道expressed函数中的main()变量在哪里被声明,并且有很多变量我没有看到本地声明您引用的main()中的内容。这通常是一种不好的做法。