我已经解决了有关从节点 JS 请求调用返回数据的问题。一个常见的错误是假设语句是逐行或同步执行的,但这里的情况并非如此。此类问题:如何从 Node.js http get 请求中获取数据。
我的问题有点不同。我编写了一个函数 getNumber() ,它返回给定查询的结果数。我想知道如何返回回调函数检索到的值?例如:
function getNumResults() {
Request(url, function(response) {
var responseJSON = JSON.parse(body);
return(responseJSON.results.count);
});
}
function Request(URL, callback) {
request(URL, function(error, response, body) {
console.log('URL: ', URL);
console.log('error: ', error);
console.log('statusCode: ', response && response.statusCode);
console.log('body: ', body);
callback(body);
});
}
如果我希望 getNumResults() 返回 responseJSON.results.count 怎么办?我怎么能这样做呢?
如果我希望 getNumResults() 返回 responseJSON.results.count 怎么办?我怎么能做到这一点?
您不能直接从
getNumResults()
返回异步值。你就是不能。该函数早在该值可用之前就返回了。这是一个时间问题。这就是异步响应的工作原理。它们会在未来某个不确定的时间完成,但它们是非阻塞的,因此 Javascript 的其余部分会继续运行,因此函数会在结果可用之前返回。
获取结果的唯一方法是使用某种回调。这适用于您的
Request()
函数和我们的 getNumResults()
函数。一旦结果是异步的,调用链中的任何人都无法逃避这一点。异步具有传染性,你永远无法从异步回到同步。因此,如果您的 getNumResults()
想要将值返回给其调用者,它要么必须本身接受回调并在获取值时调用该回调,要么必须返回一个用该值解析的承诺。
以下是如何使用 Promise 来做到这一点(这是 Javascript 异步开发的未来):
// load a version of the request library that returns promise instead of
// taking plain callbacks
const rp = require('request-promise');
function getNumResults(url) {
// returns a promise
return rp(url).then(body => {
// make the count be the resolved value of the promise
let responseJSON = JSON.parse(body);
return responseJSON.results.count;
});
}
然后,你可以像这样使用
getNumResults()
”
getNumResults(someURL).then(count => {
// use the count result in here
console.log(`Got count = ${count}`);
}).catch(err => {
console.log('Got error from getNumResults ', err);
});
仅供参考,如果您愿意,我认为您还可以通过设置适当的选项来获取
request()
库来自动解析您的 JSON 响应 {json: true}
。
编辑 2020 年 1 月 - request() 模块处于维护模式
仅供参考,
request
模块及其衍生物(如request-promise
)目前处于维护模式,不会积极开发以添加新功能。您可以在here阅读更多有关推理的信息。 此表中有一个替代方案列表,并对每个方案进行了一些讨论。我自己一直在使用 got()
,它从一开始就使用 Promise 构建,并且使用起来很简单。
2023 年,我写了 sync-request-curl。该库将帮助使用 libcurl 的 Easy 界面发送同步 HTTP 请求。
该库包含原始 sync-request 中功能的子集,但利用 node-libcurl 以获得更好的性能和 NodeJS 的附加 libcurl 选项。
这是 GET 请求的简单用法:
// import request from 'sync-request-curl';
const request = require('sync-request-curl');
const response = request('GET', 'https://ipinfo.io/json');
console.log('Status Code:', response.statusCode);
console.log('body:', response.body.toString());
console.log('json:', JSON.parse(response.body.toString());
具体到您的问题,您可以按如下方式重写代码:
const request = require('sync-request-curl');
const getNumResults = (url) => {
const response = request('GET', url);
const json = JSON.parse(response.body.toString());
return json.results.count;
};
也可以处理错误,你可以这样做
const request = require('sync-request-curl');
const getNumResults = (url) => {
try {
const response = request('GET', url);
if (response.statusCode !== 200) {
throw new Error(`GET Request fails with status ${response.statusCode}`);
}
// Error if response.body.toString() is not a JSON, e.g. server returns HTML
const json = JSON.parse(response.body.toString());
return json.results.count;
} catch (error) {
// handle error
}
};
希望这有帮助:)。