2016-03-24 6 views
0

меня в качестве основной функции следующим образом:Повторные запросы GET петлей последовательно используя Q.js

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 .. ..... п. Как я могу это достичь? Большое спасибо!

+0

Вам просто нужны результаты в порядке, когда все это делается? Если это так, запросы могут быть отправлены параллельно (гораздо быстрее, чем последовательные запросы) с небольшим кодом, чтобы убедиться, что результаты сохранены в порядке. Кроме того, ваш код не использует 'j'. Можете ли вы показать достаточно кода, чтобы мы поняли, почему цикл 'j' существует вообще, поскольку это имеет отношение к тому, как наилучшим образом решить проблему. – jfriend00

+0

@ jfriend00 Я добавил больше контекста. Мне нужно, чтобы мои запросы GET возвращались в порядке, потому что каждая предыдущая итерация основывается на предыдущем, поэтому он не может быть случайным порядком. –

+0

Просмотрите два варианта с помощью '.reduce()' в этом ответе: [Как синхронизировать последовательность обещаний?] (Http://stackoverflow.com/questions/29880715/how-to-synchronize-a-sequence-of -promises/29906506 # 29906506). – jfriend00

ответ

0

Во-первых, упростите внутренний цикл for, поставив этот код в функцию, передаваемую индексом местоположения, и затем возвращает новое обещание, когда код будет выполнен. Поскольку вы просто обрабатываете содержимое массива, вы можете использовать шаблон дизайна .reduce(), чтобы связать обещание для каждого элемента массива. Это будет выполнять их все последовательно:

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); 
     }); 
    })(i); 
} 

Это использует внутренний IIFE, чтобы захватить индекс цикла в замыкании, поэтому мы имеем правильное значение, когда вызов функции innerWork(index) выполняется через некоторое время как цепочка обещаний и выполняется вовремя.

Что это такое, это построить цепочку обещаний, которые все связаны друг с другом, а затем они начинаются спереди и выполняются один за другим.

Собираем все вместе, вы в конечном итоге с этим:

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

PS, Ваш исходный код имеет несколько необъявленных переменных, на которые вы ссылаетесь. Убедитесь, что ВСЕ переменные объявлены в соответствующей области. Например, я не знаю, где объявлена ​​переменная expressed, которая находится в вашей функции main(), и есть много переменных, для которых я не вижу локального объявления в main(), на которое вы ссылались. Это, как правило, плохая практика.