[英]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.