2014-12-23 12 views
5

Sono un po 'nuovo al nodo e sono completamente nuovo di Koa. Sto cercando di usare i generatori per fare richieste web asincrone a un'API, ma non riesco a capire come mettere insieme tutti i pezzi.Non riesco a capire come utilizzare la resa con richiesta asincrona

Come nota, sto usando bluebird perché ho visto alcuni esempi farlo e mi è sembrata una buona idea. Se c'è un modo più semplice per fare ciò che voglio senza bluebird, va benissimo anche questo.

Nel mio modulo:

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

e sto chiamando in questo modo:

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

Quando guardo nel mio console, vedo:

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

lo so il mio codice è un po 'dappertutto, ma ci ho lavorato per ore e non sono ancora più vicino a risolverlo.

Grazie!

risposta

4

prega di non chiamare promisifyAll in codice runtime: è inutile, la logica dell'applicazione ingombra, non appartiene c'è ed è molto molto lento.

È necessario contrassegnare il metodo come coroutine, altrimenti è solo un generatore.

var Promise = require("bluebird"); 
// Assumes request is promisified else where, like in your init file 
var request = require("request"); 

plugin.searchForItem = Promise.coroutine(function* (name) { 
    var response = yield request.getAsync("http://www.google.com").get(0); 
    console.log(response.statusCode); 
    return response; 
}); 

Le coroutine restituisce una promessa che si può consumare con un altro coroutine o semplicemente utilizzarlo come una promessa. Dal momento che si sta già utilizzando generatori, si potrebbe anche usare un altro coroutine:

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

Grazie un mazzo! È stato molto utile e funziona come un fascino. Ho spostato la mia parte promisifyAll in un file di init come suggerito. – snollygolly

1

Chiamare un generatore da .then non si avvicina al lavoro. Chiamare un generatore restituisce semplicemente il suo iteratore e non fa nulla con esso. Ciò che si vuole è qualcosa di simile (non testata):

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

Non è necessario fare il .then. Questo è il lavoro di Koa. Otterrà la promessa che hai fornito, attendi la risoluzione, restituisci il valore risolto come parametro a iterator.next(), che diventa la tua variabile result, e la funzione continuerà fino al prossimo yield (o alla fine della funzione).

Tuttavia, nel tuo caso, non è chiaro se desideri fornire la risposta come stai facendo nell'ultima riga. Per prima cosa, devi dare delle promesse, quindi questo probabilmente causerà un errore di run-time di Koa. Ho il sospetto che si desidera qualcosa di simile solo

this.body = response; 
0

Si potrebbe considerare l'utilizzo di un involucro request esistente, ad esempio co-request accumulo di lavorare con la libreria co che koa è costruire.

In KOA si sarebbe fare qualcosa di simile:

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

}); 
Problemi correlati