簡體   English   中英

如何在nodejs同步中進行此請求調用?

[英]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'}))

最好的部分是,這些行中的每一行都可以進行調整,直到它完成您想要的操作,而無需在每次要測試時重新運行或重新鍵入所有前面的行。 這是有效的,因為您可以從頂層直接訪問browserpages變量。

以下是它的工作原理:

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這樣的控制流模塊(我也推薦)但是你必須習慣於繼續傳遞樣式 ,因為它被稱為。

好的,首先,要保持代碼異步,您只需將相關代碼放在請求函數的回調中,這意味着它將在請求完成后運行,但不會阻止處理器處理應用程序中的其他任務。 如果您需要多次,我建議您查看Node.js中的同步請求,其中概述了各種方法以使其更加簡化並討論各種控制流庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM