2014-12-23 9 views
5

Ich bin etwas neu zu Knoten, und ich bin völlig neu in Koa. Ich versuche, Generatoren zu verwenden, um asynchrone Webanfragen zu einer API zu machen, aber ich kann nicht herausfinden, wie man alle Stücke zusammenfügt.Kann nicht herausfinden, wie yield mit async Anfrage verwenden

Als Anmerkung, ich benutze Bluebird, weil ich sah, dass einige Beispiele das tun, und es schien wie eine gute Idee. Wenn es einen einfacheren Weg gibt, ohne Bluebird zu machen, was ich will, ist das auch völlig in Ordnung.

In meinem Modul:

plugin.searchForItem = function * (name) { 
    Promise = require('bluebird'); 
    request = Promise.promisifyAll(require('request')); 
    console.log("making request"); 
    yield request.getAsync('http://apisitegoeshere.com/apicall').then(function * (result) { 
    var response = result[0]; 
    var body = result[1]; 
    console.log(response.statusCode); 
    yield response; 
    }); 
}; 

und ich es so nennen:

search.searchForShow = function (name) { 
    data = this.plugins[0].searchForItem(name); 
    console.log("search returned: " + data); 
    console.log("search returned2: " + JSON.stringify(data.next())); 
    console.log("search returned3: " + JSON.stringify(data.next())); 
    return data; 
}; 

Wenn ich in meiner Konsole sehen, ich sehe:

search returned: [object Generator] 
making request 
search returned2: {"value":{"isFulfilled":false,"isRejected":false},"done":false} 
search returned3: {"done":true} 

Ich weiß, Mein Code ist irgendwie überall, aber ich habe stundenlang daran gearbeitet, und ich bin immer noch nicht näher daran, es zu reparieren.

Danke!

Antwort

4

Bitte rufen Sie nicht promisifyAll in Runtime-Code: es ist nicht notwendig, clutters Anwendungslogik, gehört nicht da und ist sehr, sehr langsam.

Sie müssen die Methode als Coroutine markieren, sonst ist es nur ein Generator.

Die Coroutinen gibt eine Zusage, die Sie mit einer anderen Coroutine konsumieren können oder verwenden Sie es einfach als ein Versprechen. Da Sie bereits Generatoren verwenden, können Sie auch eine andere Koroutine verwenden:

search.searchForShow = Promise.coroutine(function* (name) { 
    var data = yield this.plugins[0].searchForItem(name); 
    console.log("search returned: " + data); 
    return data; 
}); 
+0

Dank einem Haufen! Das war sehr hilfreich und wirkt wie ein Zauber. Ich habe meinen PromisifyAll-Teil wie vorgeschlagen in eine Init-Datei verschoben. – snollygolly

1

Der Aufruf eines Generators von .then wird nicht annähernd funktionieren. Das Aufrufen eines Generators gibt nur seinen Iterator zurück und tut nichts damit. Was Sie wollen, ist so etwas wie (nicht getestet):

plugin.searchForItem = function * (name) { 
    Promise = require('bluebird'); 
    request = Promise.promisifyAll(require('request')); 
    console.log("making request"); 
    var result = yield request.getAsync('http://apisitegoeshere.com/apicall'); 
    var response = result[0]; 
    var body = result[1]; 
    console.log(response.statusCode); 
    yield response; 
}; 

Sie brauchen nicht die .then zu tun. Das ist Koas Job. Es wird das Versprechen erhalten, das Sie ergaben, warten Sie, bis es aufgelöst wird, geben Sie den aufgelösten Wert als Parameter an iterator.next() zurück, der Ihre Variable result wird, und die Funktion wird zu dem nächsten yield (oder dem Ende der Funktion) fortgesetzt.

In Ihrem Fall ist es jedoch nicht klar, dass Sie die Antwort wie in der letzten Zeile erhalten möchten. Zum einen müssen Sie Versprechungen machen, was wahrscheinlich einen Koa-Laufzeitfehler verursacht. Ich vermute, Sie wollen etwas wie nur

this.body = response; 
0

Sie betrachten könnte eine bestehende request Wrapper, wie co-request Build mit der co Bibliothek zu arbeiten, die koa auf ist zu bauen.

In koa würden Sie so etwas wie:

// server.js 
var request = require('co-request'); 

app.use(function *(){ 
    try{ 
     var result = yield request('http://apisitegoeshere.com/apicall');  
     this.body = result.body; 
    } 
    catch(err){ 
     this.throw(500); 
    } 

}); 
Verwandte Themen