如何在nodejs同步中进行此请求调用?

Tri*_*daz 19 javascript request node.js

我的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;
}
Run Code Online (Sandbox Code Playgroud)

此外,我已经阅读过关于'事件'以及节点是如何'偶像'的,我应该在编写代码时尊重它.我很高兴这样做,但我必须有一种方法来确保我在继续我的应用程序的控制流之前从uri获得源代码 - 所以如果不是通过使函数同步,那怎么办呢? ?

abb*_*bbr 17

您可以使用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;
}
Run Code Online (Sandbox Code Playgroud)


Lai*_*uan 16

您应该避免同步请求.如果你想要同步控制流,你可以使用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)
});
Run Code Online (Sandbox Code Playgroud)

process是答应要运行 get_source_at的回报.

  • "你应该避免同步请求"不是一个准确的一揽子声明.您应该避免在应用程序的主线程上执行同步请求,或者在导致UI阻塞的情况下.但在这种情况下,无头网络服务的唯一目的是委托给其他一些网络服务并报告结果?有一个同步请求是完全正常的,事实上,异步请求更好/更清洁.了解您的用例非常重要,并选择最适合的解决方案.这不是一个总是一个而不是另一个的情况. (43认同)
  • 同意@aroth - 我正在使用nodejs脚本进行自定义复杂的部署任务,我需要严格按顺序执行每个命令.我可以使用promises,但即使`then()`链接也会有点难看,如果你有超过10个任务以严格的顺序运行. (3认同)
  • 那不是这个问题的答案。 (3认同)

Vik*_*tam 10

这是使用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)
Run Code Online (Sandbox Code Playgroud)

请参考deasync的文档,你会发现,你可以使用
desync(function (n params, cb) {})
,使功能在那里cb应该回来与(err, data).因此fs.readFile()功能可以很容易地包装deasync功能.但是对于request那些不回来的功能cb(err, data).您可以使用自定义cb(err, data)回调格式创建自己的函数(命名或匿名),就像我在上面的代码中所做的那样.通过这种方式,您可以通过等待回调cb(err, data)返回到不同的javascript层来强制几乎所有异步函数执行同步(如文档所述).另外,请确保已经涵盖了使用cb(err, data)回调取消同步从函数中退出的所有方法,否则您的程序将被阻止.

希望,它可以帮助那里的人!

更新:
不要使用这种方式执行同步请求.使用Async/Await写入基于同步查找代码的promises.您可以使用request-promise-nativenpm模块来避免使用promises包装请求模块.