繁体   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