2016-12-16 6 views
0

Ich versuche, warf eine Liste der Artikel iterieren und einige Aktionen auf sie tun, indem sie eine API wie in diesem Beispiel nennen:asynchrone Ausgabe mit Schleife in NodeJS

for (i = 0; i < arr.length; i++) { 
    if (arr[i].id == 42) { 
     api.requestAction(arr[i].id, function(error, response){ }); 
    } 
} 

Problem ist die Schleife offensichtlich beendet, bevor alle Anfragen werden gemacht und das Programm beendet. Was soll ich tun, um es zu verwalten? Ich habe die "Promise" -Methode gesehen, weiß aber nicht, wie ich sie in diesem Fall verwenden kann, oder vielleicht gibt es eine andere Lösung.

Vielen Dank im Voraus!

+0

Sind Sie eine 'Promise' Bibliothek? – Shaharyar

+0

Nein, ich benutze es nicht, weil ich nicht wirklich weiß, wie ich damit umgehen soll. – slidefizz

+0

@shaharyar von OP: * Ich sah die "Promise" -Methode aber nicht wirklich, wie ich es in diesem Fall verwenden kann oder vielleicht gibt es eine andere Lösung * – Derek

Antwort

1

Sie könnten async.js verwenden. Es ist eine asynchrone Control-Flow-Bibliothek, die Kontrollflüsse für Dinge wie sequenzielle Schleifen, Parallelsschleife und viele andere übliche Flusskontrollmechanismen bietet.

Siehe Code unten, der Code geht davon aus, dass Sie Variable "arr" irgendwo im Bereich definiert ist.

npm installieren async

 var async = require("async"); 




    //Loop through each item, waiting for your 
    //asyncronous function to finish before continuing 
    //to move onto the next item in the array 
    //NOTE: This does not loop sequentially, if you want that function with asyncjs then user eachSeries 
    async.each(arr, 

     //Item is the current item being iterated over, 
     //callback is the callback you call to finish the current iteration, it accepts an error and result parameter callback(error, result); 
     function (item, callback) { 
       api.requestAction(item.id, function(error, response){ 

        //Check for any errors...  
        if (error) return callback(error); 
        callback(null); 
       }); 
     }, 
     function (err, result) { 
       //You've now finished the loop 

       if (err) { 
       //Do something, you passed an error object to 
       //in one of the loop's iterations 
       } 

       //No errors, move on with your code.. 
     }); 
+0

warum wickelst du es in einen Verschluss? – Endless

+0

Kraft der Angewohnheit, nur entfernt die Umhüllung Schließung :) Ich wickle in der Regel alle Schnipsel in Schließung, so dass ich kopieren und einfügen kann, versichert der Code wird nichts anderes im Ziel Skript zu brechen.Ein guter Ruf für die Lesbarkeit der Antwort! –

1

Mit node-fetch (ein promisify http api) können Sie zusammen mit Asynchron/await halt die for-Schleife, bis es fertig ist, aber dies erfordert Knoten v6 + mit --harmony-async-await Flagge

const fetch = require('node-fetch') 

async function foo() { 
    for (let item of arr) { 
    if (item.id == 42) { 
     let res = await fetch(url) 
     let body = await res.text() 
     console.log(body) 
    } 
    } 
    console.log('done (after request)') 
} 
hinzugefügt

jetzt jedes Mal, wenn Sie das async-Schlüsselwort vor einer Funktion hinzufügen, gibt es immer eine Zusage zurück, die auflöst/ablehnt, wenn alles erledigt ist

foo().then(done, fail) 

alternetive können Sie einfach wickeln Sie in ein Versprechen api fn wenn Sie wollen Knoten-Fetch

await new Promise((rs, rj) => { 
    api.requestAction(arr[i].id, function(error, response){ 
    error ? rj(error) : rs(response) 
    }) 
}) 
0

Verwenden Drossel Versprechen nicht installieren:

var Promise = require('bluebird'); 

Promise.map(arrayOfIds, function(item){ 
    return api.requestAction(item); 
}) 
.then(function(response){ 
// all the requests are resolved here 
}) 

wenn u wollen sequenzielle Ausführung der IDs verwenden Sie dann Promise.mapSeries (ist langsam, wie es wartet auf die Aufgabe zu beenden)

+0

ya Ihre Lösung macht Sinn, ich habe nicht gesehen, dass er die Schleife gestoppt hat, danke für die Erwähnung –

1

Installieren Sie bluebird

npm install bluebird --save 

-Code

//require npm 
var Promise = require("bluebird"); 

//code 
//"promisify" converts traditional callback function into a Promise based function 
var _requestAction = Promise.promisify(api.requestAction); 

//loop over array 
Promise.map(arr, function (value) { 
    if (value.id == 42) { 
     //async request 
     return _requestAction(value.id).then(function (_result) { 
      //success 
      console.log(_result); 
     }).catch(function (e) { 
      //error 
      console.error(e); 
     }); 
    } 
}); 
+0

var _requestAction = Promise.promisify (api.requestAction); Hier ist api.requestAction ein Funktionsaufruf rechts. –

+0

Nein, es ist in "Versprechen" umzuwandeln. Ich habe eine Erklärung hinzugefügt. – Shaharyar

Verwandte Themen