2016-08-03 3 views
1

Ich habe eine Reihe von Funktionen verwendet, um Daten für meinen Dienst bereitzustellen. Ich möchte jeden von ihnen durchlaufen und anhalten, sobald einer von ihnen das gewünschte Ergebnis zurückgibt. Wenn der erste funktioniert, ist das in Ordnung. Wenn es eine Ausnahme oder Daten nicht gültig ist, möchte ich zum nächsten usw. gehen.bluebirdjs verspricht in eine for-Schleife gewickelt

Wie kann ich das erreichen? Ich habe den folgenden Code:

handleData: function(address) { 
    var self = this; 
    return new Promise(function (resolve, reject) { 
    for (var i = 0; i < self.listAllAvailableProviders.length; ++i) { 
     var handler = self.listAllAvailableProviders[i]; 
     new handler().getData(address) 
     .then(function(value) { 
      Logger.info(value); 
      resolve(value); 
     }) 
     .catch(function(err){ 
      Logger.error(err); 
     }) 
    } 
    reject(""); 
    }); 
} 

Wie kann ich es beheben, um zu stoppen, sobald der erste die richtigen Daten bekommt? Ich habe die bluebirdjs Dokumentation vergeblich durchgelesen.

EDIT Ich habe eine break Aussage nach resolve und ich habe dies:

SyntaxError: Illegal break statement 
at Object.exports.runInThisContext (vm.js:53:16) 
at Module._compile (module.js:513:28) 
at Object.Module._extensions..js (module.js:550:10) 
at Module.load (module.js:458:32) 
at tryModuleLoad (module.js:417:12) 
at Function.Module._load (module.js:409:3) 
at Module.require (module.js:468:17) 
at require (internal/module.js:20:19) 
+0

Sie führen alle Ihre Anforderungen parallel im 'für 'Schleife. Wenn Sie ein Ergebnis gefunden haben, das Ihnen gefällt, wurden alle anderen Anfragen bereits gestartet. Sie können Ihre Anfragen nacheinander einzeln serialisieren und dann erst mit der nächsten Anfrage fortfahren, wenn Sie keine Antwort gefunden haben, die Ihnen gefällt. Ist es das was du willst? – jfriend00

+0

Können Sie die Serialisierung einzeln erklären? Ich möchte die erste, die Erfolg hat, also wenn die eine nicht funktioniert, dann versuche die nächste. Dies verwendet 'sailsjs'. – KVISH

+0

Erkläre was? Ich weiß nicht, welchen Teil meines Kommentars Sie nicht verstanden haben. Möchten Sie Ihre Anfragen serialisieren (einzeln ausführen)? – jfriend00

Antwort

2

Sie alle Ihre Anfragen parallel in der for Schleife laufen so, wenn Sie einen finden, der einen Wert hat man so will, die andere haben bereits damit begonnen worden, so gibt es keine Möglichkeit, „nicht“ führe sie aus. Wenn Sie die anderen nicht ausführen möchten, nachdem Sie eine gefunden haben, müssen Sie sie nicht parallel starten. Das würde Sie zu einem Designmuster führen, in dem Sie die Anfragen serialisieren. Führen Sie einen aus, wenn es nicht erfolgreich ist, führen Sie den nächsten aus und so weiter.

Wie ich am besten weiß, gibt es in Bluebird kein integriertes Schema, um das zu tun, was Sie fragen. Die einfachste Sache, die ich mir vorstellen kann, ist, eine der Array-Verarbeitungsfunktionen in Bluebird zu verwenden, die nacheinander die Anfragen serialisiert, wie zum Beispiel Promise.mapSeries(), und dann eine Ablehnung verwendet, um die Verarbeitung abzubrechen, wenn Sie einen guten Wert gefunden haben.

handleData: function(address) { 
    return Promise.mapSeries(this.listAllAvailableProviders, function(handler) { 
     return new handler().getData(address).then(function(value) { 
      // the first success we get, we will throw with 
      // the returned value in order to stop the .mapSeries progression 
      throw value; 
     }, function(err) { 
      // log the error, but don't let the rejection propagate so other handlers are called 
      Logger.error(err); 
     }) 
    }).then(function() { 
     // nothing succeeded here, turn it into an overall rejection 
     throw new Error("No getData() handlers succeeded");   
    }, function(val) { 
     // reject here means we got a good value so turn it into a resolved value 
     return val; 
    }) 
} 


// usage 
obj.handleData().then(function(val) { 
    // got value here 
}).catch(function(err) { 
    // no values here 
}); 

Merkwürdigerweise scheint es weniger Code zu sein und vielleicht ein bisschen einfacher, wenn Sie nur die Handler selbst iterieren:

handleData: function(address) { 
    var index = 0; 
    var handlers = this.listAllAvailableProviders; 
    var handlerCnt = handlers.length; 

    function next() { 
     if (index < handlerCnt) { 
      var handler = handlers[index++]; 
      return new handler().getData(address).catch(next); 
     } else { 
      return Promise.reject(new Error("No handler found for address")); 
     } 
    } 
    return next(); 
} 
+0

Ihre zweite Antwort war richtig! Macht auch sehr viel Sinn. – KVISH

+0

@KVISH - Ich mag die zweite auch, aber ich denke, ich habe das Problem mit der ersten behoben. – jfriend00

0

wenn Versprechungen helfen könnte nicht eine harte Einschränkung sind caolan/async#eachSeries oder ähnliches. So etwas wie ...

// var Promise = require(?) 
// var async = require("async") 
handleData: asyncProviderFinder 

... 

function asyncProviderFinder(address){ 
    var self = this; 
    return new Promise(function(resolve, reject){ 
    async.eachSeries(
     self.listAllAvailableProviders, 
     function iterate(provider, next){ 
     var handler = provider; 
     new handler().getData(address) 
     .then(function(value){ 
      Logger.info(value); 
      next("abort"); // callback any error to abort future iterations 
      return resolve(value); 
     }) 
     .catch(function (err){ 
      Logger.error(err); 
      next(); 
     }); 
     }, 
     function callback(err, firstProvider){ 
     if ((firstProvider === undefined) && !err){ reject(""); } 
     } 
    ); 
    }); 
} 
+0

nicht mit dieser Bibliothek vertraut. Aber dein Code läuft nicht einmal, wenn ich die Bibliothek installiere und 'var async = require (" async ");'? – KVISH

+0

erhalte ich die Fehlermeldung: 'return new Promise (Funktion resolve, ablehnen) { ^ Syntaxerror: unerwartete Token, bei Object.exports.runInThisContext (vm.js: 53: 16) bei Module._compile (module.js : 513: 28) ' – KVISH

+0

' return new Promise (Funktion (auflösen, ablehnen) {}) ' – Seth