[英]How can I make this call to request in nodejs synchronous?
我的nodejs應用程序中有一個名為get_source_at的函數。 它需要一個uri作為參數,其目的是從該uri返回源代碼。 我的問題是我不知道如何使函數同步調用請求,而不是給它回調函數。 我希望控制流停止加載uri所需的幾秒鍾。 我怎樣才能做到這一點?
function get_source_at(uri){
var source;
request({ uri:uri}, function (error, response, body) {
console.log(body);
});
return source;
}
此外,我已經閱讀過關於'事件'以及節點是如何'偶像'的,我應該在編寫代碼時尊重它。 我很高興這樣做,但我必須有一種方法來確保我在繼續我的應用程序的控制流之前從uri獲得源代碼 - 所以如果不是通過使函數同步,那怎么辦呢? ?
您可以使用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;
}
您應該避免同步請求。 如果你想要同步控制流,你可以使用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)
});
承諾在 get_source_at
返回后運行該process
。
這是使用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>(.*?)<\/title>/
var myTitle = getHtml("http://www.yahoo.com").match(title)[1]
console.log(myTitle)
請參閱deasync文檔 ,您會發現可以使用
desync(function (n params, cb) {})
使cb
應該返回的函數 (err, data)
。 所以fs.readFile()
類的函數可以用deasync
函數輕松包裝。 但對於像cb(err, data)
沒有回來的request
這樣的函數。 您可以使用自定義cb(err, data)
回調格式創建自己的函數(命名或匿名),就像我在上面的代碼中所做的那樣。 通過這種方式,您可以通過等待回調cb(err, data)
返回到不同的javascript層來強制幾乎所有異步函數執行同步(如文檔所述)。 還要確保你已經涵蓋了從使用cb(err, data)
回調的deasync包裝的函數中退出的所有方法,否則你的程序將被阻止。
希望,它可以幫助那里的人!
更新:
不要使用這種方式進行同步請求。 使用Async / Await寫入基於同步查找代碼的promises。 您可以使用request-promise-native
npm模塊來避免使用promises包裝請求模塊。
具有簡單的阻塞功能是交互式開發的一大福音! sync
功能(定義如下)可以同步任何承諾,大大減少了使用API和學習它所需的語法量。 例如,以下是如何將它與puppeteer庫一起用於無頭Chrome:
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'}))
最好的部分是,這些行中的每一行都可以進行調整,直到它完成您想要的操作,而無需在每次要測試時重新運行或重新鍵入所有前面的行。 這是有效的,因為您可以從頂層直接訪問browser
和pages
變量。
以下是它的工作原理:
const deasync = require("deasync");
const sync = deasync((promise, callback) => promise.then(result) => callback(null, result)));
它使用其他答案中提到的deasync包。 deasync
為匿名函數創建一個部分應用程序,它將callback
作為最后一個參數添加,並阻塞直到callback
。 callback
接收錯誤條件作為其第一個參數(如果有),結果作為其第二個參數(如果有)。
在繼續我的應用程序的控制流之前,我必須有辦法確保我有來自uri的源代碼 - 所以如果不是通過使函數同步,那怎么辦呢?
鑒於您的應用程序的這個入口點:
function app(body) {
// Doing lots of rad stuff
}
你拿起身體開始它:
request({ uri: uri }, function (error, response, body) {
if(err) return console.error(err);
// Start application
app(body);
}
這是在編寫node.js(和一般的javascript)時必須習慣的東西。 有像async這樣的控制流模塊(我也推薦)但是你必須習慣於繼續傳遞樣式 ,因為它被稱為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.