2016-03-24 4 views
0

Ich habe als Hauptfunktion wie folgt:Rückkehr geschleift GET-Anfragen unter Verwendung von Q.js sequentiell

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 
} 

Als ich den Standort console.log values[0] nicht in Ordnung ist, wenn es 0,1,2 sein sollte .. ..... n. Wie kann ich das erreichen? Danke vielmals!

+0

Brauchen Sie nur die Ergebnisse in der Reihenfolge, wenn sie alle fertig sind? Wenn dies der Fall ist, können die Anfragen parallel (viel schneller als sequenzielle Anfragen) mit ein wenig Code gesendet werden, um sicherzustellen, dass die Ergebnisse in Ordnung bleiben. Außerdem verwendet Ihr Code kein 'j'. Können Sie bitte genügend Code zeigen, damit wir verstehen, warum die "j" -Schleife überhaupt vorhanden ist, da dies relevant ist, um das Problem am besten zu lösen. – jfriend00

+0

@ jfriend00 Ich habe mehr Kontext hinzugefügt. Ich brauche meine GET-Anfragen, um in der Reihenfolge zurückzukommen, weil jede vorherige Iterationen auf der vorherigen aufbaut, so dass es keine zufällige Reihenfolge sein kann. –

+0

Sehen Sie sich die zwei Optionen mit '.reduce()' in dieser Antwort an: [Wie man eine Sequenz von Versprechen synchronisiert?] (Http://stackoverflow.com/questions/29880715/how-to-synchronize-a-sequence-of -Promises/29906506 # 29906506). – jfriend00

Antwort

0

Lassen Sie zunächst die innere for-Schleife vereinfachen, indem Sie diesen Code in eine Funktion einfügen, die den Standortindex übergibt und dann eine neue Versprechung zurückgibt, wenn der Code fertig ist. Da Sie nur den Inhalt eines Arrays verarbeiten, können Sie mit dem Entwurfsmuster .reduce() ein Versprechen für jedes Arrayelement verketten. Dies wird ihnen alle seriell ausführen:

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

Dann kann die äußere Schleife durch nur manuell so zu einem einzigen Versprechen Verkettungs erfolgen:

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

Dadurch wird die interne IIFE verwendet den Schleifenindex zu erfassen in einer Schließung, so haben wir den richtigen Wert, wenn der Funktionsaufruf innerWork(index) irgendwann später als die Versprechen Kette und rechtzeitig ausgeführt werden.

Was dies tut, ist eine Kette von Versprechen, die alle miteinander verbunden sind, und dann beginnen sie an der Front und führen nacheinander aus.

setzen sie alle zusammen, erhalten Sie auf den Punkt:

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

Sie bitte auch die verbesserte getLocation() Funktion von Ihrer anderen Frage/Antwort erinnern:

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, Ihre Original-Code hat mehrere nicht deklarierte Variablen, auf die Sie verweisen. Stellen Sie sicher, dass alle Variablen im entsprechenden Bereich deklariert sind. Zum Beispiel weiß ich nicht, wo die expressed Variable, die in Ihrer main()-Funktion ist, deklariert wird, und es gibt viele Variablen, für die ich keine lokale Deklaration in main() sehen, die Sie referenzierten. Das ist generell eine schlechte Übung.

Verwandte Themen