Kaip atlikti funkciją, kol atgalinis skambutis bus vadinamas naudojant „node.js“

Turiu supaprastintą funkciją, kuri atrodo taip:

 function(query) { myApi.exec('SomeCommand', function(response) { return response; }); } 

Iš esmės, aš noriu, kad jis skambintų myApi.exec ir grąžintų atsakymą, kuris yra nurodytas atgalinio ryšio lambda. Tačiau minėtas kodas neveikia ir tiesiog grįžta iš karto.

Tik bandydamas labai įsilaužėlių bandžiau toliau, kuris neveikė, bet bent jau supratote, ką bandau atlikti:

 function(query) { var r; myApi.exec('SomeCommand', function(response) { r = response; }); while (!r) {} return r; } 

Iš esmės tai, kas yra geras „node.js / įvykis“, kaip tai padaryti? Noriu, kad mano funkcija lauktų atgalinio ryšio, o tada grąžintų jai perduotą vertę.

173
16 февр. Chris 16 vasaris 2011-02-16 01:30 '11 at 1:30 2011-02-16 01:30
@ 10 atsakymų

„Geras node.js / įvykis“, kaip tai padaryti, nėra laukti .

Kaip ir visa kita, kai dirbate su įvykių valdomomis sistemomis, tokiomis kaip mazgas, jūsų funkcija turi priimti atgalinio ryšio parametrą, kuris bus iškviestas užbaigus skaičiavimą. Skambintojas neprivalo laukti, kol vertė bus grąžinta įprastu būdu, bet siunčia procedūrą, kuri apdoros gautą vertę:

 function(query, callback) { myApi.exec('SomeCommand', function(response) { // other stuff here... // bla bla.. callback(response); // this will "return" your value to the original caller }); } 

Taigi, nenaudokite jo taip:

 var returnValue = myFunction(query); 

Tačiau taip:

 myFunction(query, function(returnValue) { // use the return value here instead of like a regular (non-evented) return value }); 
216
16 февр. Jakobo atsakymas vasario 16 d. 2011-02-16 01:35 '11 at 1:35 2011-02-16 01:35

patikrinkite jį: https://github.com/luciotato/waitfor-ES6

jūsų kodas su wait.for: (reikia generatorių, --harmonijos vėliavos)

 function* (query) { var r = yield wait.for( myApi.exec, 'SomeCommand'); return r; } 
15
06 дек. Lucio M. Tato atsakymas gruodis 06 2013-12-06 17:27 '13, 17:27, 2013-12-06 17:27

Jei nenorite naudoti atgalinio ryšio, galite naudoti „Q“ modulį.

Pavyzdžiui:

 function getdb() { var deferred = Q.defer(); MongoClient.connect(databaseUrl, function(err, db) { if (err) { console.log("Problem connecting database"); deferred.reject(new Error(err)); } else { var collection = db.collection("url"); deferred.resolve(collection); } }); return deferred.promise; } getdb().then(function(collection) { // This function will be called afte getdb() will be executed. }).fail(function(err){ // If Error accrued. }); 

Daugiau informacijos rasite šiuo adresu : https://github.com/kriskowal/q

9
17 апр. atsakymas pateikiamas 17 val. 2015-04-17 10:17 '15 - 10:17 2015-04-17 10:17

Pastaba Šis atsakymas tikriausiai neturėtų būti naudojamas gamybos kode. Tai yra įsilaužimas, ir jūs turėtumėte žinoti pasekmes.

Yra „ uvrun“ modulis (atnaujintas naujoms „Nodejs“ versijoms čia ), kur galite paleisti vieną pagrindinio „libuv“ įvykių ciklo ciklą (kuris yra pagrindinis „Nodejs“ ciklas).

Jūsų kodas bus toks:

 function(query) { var r; myApi.exec('SomeCommand', function(response) { r = response; }); var uvrun = require("uvrun"); while (!r) uvrun.runOnce(); return r; } 

(Galite naudoti alternatyvą uvrun.runNoWait() . Tai gali išvengti kai kurių blokavimo problemų, tačiau reikia 100% procesoriaus.)

Atkreipkite dėmesį, kad šis metodas panaikina visą „Nodejs“ tikslą, t.y. turėti visus asinchroninius ir neužblokuotus. Be to, jis gali žymiai padidinti skambučio gylį, kad galėtumėte susidurti su stekų perpildymu. Jei rekursiškai pradėsite tokią funkciją, neabejotinai susidursite su problemomis.

Žr. Kitus atsakymus, kaip pakeisti kodą, kad jis būtų teisingas.

Šis sprendimas yra naudingas tik bandymams ir ypač. norite sinchronizuoti ir serijinį kodą.

5
27 марта '14 в 10:32 2014-03-27 10:32 Albert atsakė kovo 27 d. 14 d. 10:32 2014-03-27 10:32

Jis nugalės ne blokavimo I / O tikslą - blokuojate, kai jam nereikia blokuoti :)

Turite užklijuoti savo atšaukimus vietoj to, kad priverstumėte laukti „node.js“, arba paskambinkite į kitą atgalinį ryšį, kur jums reikia rezultato r .

Labiausiai tikėtina, kad, jei norite priversti blokuoti, manote, kad neteisingai vertinate savo architektūrą.

3
16 февр. atsakymą pateikė rfw 16 vasaris . 2011-02-16 01:33 '11 at 1:33 2011-02-16 01:33

Jei norite, kad tai būtų labai paprasta ir paprasta, jokios fantastinės bibliotekos negali tikėtis, kad atgalinio ryšio funkcijos bus vykdomos mazge, prieš vykdant bet kurį kitą kodą, atrodo taip:

 //initialize a global var to control the callback state var callbackCount = 0; //call the function that has a callback someObj.executeCallback(function () { callbackCount++; runOtherCode(); }); someObj2.executeCallback(function () { callbackCount++; runOtherCode(); }); //call function that has to wait continueExec(); function continueExec() { //here is the trick, wait until var callbackCount is set number of callback functions if (callbackCount < 2) { setTimeout(continueExec, 1000); return; } //Finally, do what you need doSomeThing(); } 
3
19 дек. Atsakymą pateikė Marquinho Peli gruodžio 19 d. 2016-12-19 02:59 '16 at 2:59 2016-12-19 02:59

Nuo mazgo 4.8.0 galite naudoti ES6 funkciją, vadinamą generatoriumi. Jūs galite sekti šį straipsnį gilesnėms sąvokoms. Bet iš esmės jūs galite naudoti generatorius ir žada atlikti šį darbą. Aš naudoju bluebird, kad pažadėtum ir valdytumėte generatorių.

Jūsų kodas turi būti toks pat kaip ir toliau pateiktame pavyzdyje.

 const Promise = require('bluebird'); function* getResponse(query) { const r = yield new Promise(resolve => myApi.exec('SomeCommand', resolve); return r; } Promise.coroutine(getResponse)() .then(response => console.log(response)); 
2
09 марта '17 в 15:30 2017-03-09 15:30 atsakymą pateikė „ Douglas Soares“ kovo 9 d. 17 val. 15:30 2017-03-09 15:30

Tarkime, kad turite funkciją:

 var fetchPage(page, callback) { .... request(uri, function (error, response, body) { .... if (something_good) { callback(true, page+1); } else { callback(false); } ..... }); }; 

Galite naudoti tokius skambučius:

 fetchPage(1, x = function(next, page) { if (next) { console.log("^^^ CALLBACK --> fetchPage: " + page); fetchPage(page, x); } }); 
1
11 июля '13 в 10:50 2013-07-11 10:50 atsakymas pateikiamas Z0LtaR liepos 11 d. 13 val. 10:50 2013-07-11 10:50

Jis dirbo, kad galėčiau naudoti

 JSON.parse(result)['key'] 

apie numatomą rezultatą. Tai negali būti „super general“, bet pabaigoje „JSON.parse“ pavyko laukti asinchroninio skambučio ir neatliko result['key'] .

1
25 марта '15 в 16:39 2015-03-25 16:39 atsakymas į M.Muc Mic'ą pateikiamas kovo 15 d. 15, 16:39 2015-03-25 16:39
 exports.dbtest = function (req, res) { db.query('SELECT * FROM users', [], res, renderDbtest); }; function renderDbtest(result, res){ res.render('db', { result: result }); } 

Taip aš tai padariau, jums tiesiog reikia perkelti „res“ su juo, kad galėtumėte tai padaryti vėliau

0
31 окт. atsakymas duodamas pagal harmoniją . 2015-10-31 18:14 '15, 18:14, 2015-10-31 18:14

Kiti klausimai apie „ etiketes arba Užduoti klausimą