Come posso effettuare questa chiamata alla richiesta in nodejs sincrono?

Ho una funzione nella mia applicazione nodejs chiamata get_source_at. Ci vuole un uri come argomento e il suo scopo è quello di restituire il codice sorgente da quel uri. Il mio problema è che non so come rendere la funzione chiamata in modo sincrono, piuttosto che dargli quella funzione di callback. Voglio che il stream di controllo si fermi per i pochi secondi necessari per caricare l’uri. Come posso raggiungere questo objective?

function get_source_at(uri){ var source; request({ uri:uri}, function (error, response, body) { console.log(body); }); return source; } 

Inoltre, ho letto di “eventi” e di come il nodo è “evented” e dovrei rispettarlo nello scrivere il mio codice. Sono felice di farlo, ma devo avere un modo per assicurarmi di avere il codice sorgente da un uri prima di continuare il stream di controllo della mia applicazione – quindi se ciò non avviene rendendo la funzione sincrona, come può essere fatta ?

Dovresti evitare le richieste sincrone. Se vuoi qualcosa come il stream di controllo sincrono, puoi usare async .

 async.waterfall([ function(callback){ data = get_source_at(uri); callback(null, data); }, function(data,callback){ process(data, callback); }, ], function (err,result) { console.log(result) }); 

Si promette che il process verrà eseguito dopo il ritorno di get_source_at .

È ansible con deasync :

 function get_source_at(uri){ var source; request({ uri:uri}, function (error, response, body) { source = body; console.log(body); }); while(source === undefined) { require('deasync').runLoopOnce(); } return source; } 

Questo è il modo migliore per usare deasync.

 var request = require("request") var deasync = require("deasync") var getHtml = deasync(function (url, cb) { var userAgent = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36"} request({ url: url, headers: userAgent }, function (err, resp, body) { if (err) { cb(err, null) } cb(null, body) }) }) var title = /(.*?)<\/title>/ var myTitle = getHtml("http://www.yahoo.com").match(title)[1] console.log(myTitle) 

Si prega di fare riferimento alla documentazione di deasync , troverete che è ansible utilizzare
desync(function (n params, cb) {})
per rendere la funzione in cui cb dovrebbe tornare (err, data) . Quindi le funzioni simili a fs.readFile() possono essere facilmente deasync con la funzione deasync . Ma per funzioni come la request che non ritorna con cb(err, data) . È ansible rendere la propria funzione (denominata o anonima) con un formato di callback personalizzato cb(err, data) esattamente come ho fatto nel codice precedente. In questo modo puoi forzare quasi tutte le funzioni asincrone ad eseguire la sincronizzazione aspettando che callback cb(err, data) ritorni su un diverso livello javascript (come dice la documentazione). Assicurarsi inoltre di aver coperto tutti i modi per uscire dalla funzione che si sta eseguendo con deasync con callback cb(err, data) , altrimenti il ​​programma si bloccherà.

Spero, aiuti qualcuno là fuori!

Aggiornare:
Non usare questo modo di fare richieste sincrone. Usa Async / Attendi per scrivere codice basato su sincrono promesse. È ansible utilizzare il modulo npm request-promise-native per evitare il wrapping del modulo di richieste con promesse da soli.

Avere una semplice funzione di blocco è un grande vantaggio per lo sviluppo interattivo! La funzione di sync (definita di seguito) può sincronizzare qualsiasi promise, riducendo drasticamente la quantità di syntax necessaria per giocare con un’API e apprenderla. Ad esempio, ecco come usarlo con la libreria burattinai per Chrome senza testa:

 var browser = sync(puppeteer.connect({ browserWSEndpoint: "ws://some-endpoint"})); var pages = sync(browser.pages()) pages.length 1 var page = pages[0] sync(page.goto('https://duckduckgo.com', {waitUntil: 'networkidle2'})) sync(page.pdf({path: 'webpage.pdf', format: 'A4'})) 

La parte migliore è che ciascuna di queste linee può essere ottimizzata fino a quando non fa ciò che si desidera, senza dover rieseguire o digitare nuovamente tutte le righe precedenti ogni volta che si desidera testarlo. Funziona perché hai accesso diretto al browser e alle variabili delle pages dal livello più alto.

Ecco come funziona:

 const deasync = require("deasync"); const sync = deasync((promise, callback) => promise.then(result) => callback(null, result))); 

Usa il pacchetto deasync menzionato in altre risposte. deasync crea un’applicazione parziale alla funzione anonima, che aggiunge la callback come ultimo argomento e blocca fino a quando non viene callback richiamata. callback riceve la condizione di errore come primo argomento (se presente) e il risultato come secondo (se presente).

Devo avere un modo per assicurarmi di avere il codice sorgente da un uri prima di continuare il stream di controllo della mia applicazione – quindi se ciò non avviene rendendo la funzione sincrona, come può essere fatta?

Dato questo punto di accesso alla tua applicazione:

 function app(body) { // Doing lots of rad stuff } 

Lo dai calci recuperando il corpo:

 request({ uri: uri }, function (error, response, body) { if(err) return console.error(err); // Start application app(body); } 

Questo è qualcosa su cui ti devi abituare durante la programmazione di node.js (e javascript in generale). Ci sono moduli di controllo del stream come asincrono (che anch’io consiglio) ma bisogna abituarsi allo stile di passaggio di continuazione , come viene chiamato.

Ok, prima di tutto, per mantenere il codice asincrono è sufficiente posizionare il codice pertinente all’interno del callback della funzione di richiesta, il che significa che verrà eseguito dopo che la richiesta è stata completata, ma non impedirà al processore di gestire altre attività nell’applicazione. Se ne hai bisogno più volte ti consiglio di verificare la richiesta sincrona in Node.js che delinea vari metodi per renderla più snella e discute le varie librerie del stream di controllo.