我对nodejs有点陌生,因此我先要道歉,因为我缺少明显的东西。在下面的代码中,我从api获取json数据。
let data_json = ''; // global variable
app.get('/', (req, res) => {
request('http://my-api.com/data-export.json', (error, response, body) => {
data_json = JSON.parse(body);
console.log( data_json ); // data prints successfully
});
console.log(data_json, 'Data Test - outside request code'); // no data is printed
})
data_json是我的全局变量,我分配了请求函数返回的数据。在该函数中,json数据可以正常打印。但是我尝试在请求功能之外打印相同的数据,但是什么也没打印出来。
请帮助我理解原因并更正我犯的任何错误。
console.log出现在您的请求之前,请查看获取异步数据的方法:回调,承诺或异步等待。
而不是等待请求解决(从您的API获取数据),Node.js会在外部执行代码,并且它不会打印任何内容,因为在执行时以及在节点从您的节点获取数据之后仍然没有任何内容api(将花费几毫秒),它将在请求内执行代码。这是因为nodejs是异步且非阻塞的语言,这意味着它在您的api返回数据之前不会阻塞或停止代码,它只会继续运行并在获得响应后稍后结束。
这是在回调函数中进行所需的所有数据操作的一种好习惯,不幸的是,您不能依赖于您拥有的结构。
这是您的代码示例,只是注释了操作顺序:
let data_json = ''; // global variable
app.get('/', (req, res) => {
//NodeJS STARTS executing this code
request('http://my-api.com/data-export.json', (error, response, body) => {
//NodeJS executes this code last, after the data is loaded from the server
data_json = JSON.parse(body);
console.log( data_json );
//You should do all of your data_json manipluation here
//Eg saving stuff to the database, processing data, just usual logic ya know
});
//NodeJS executes this code 2nd, before your server responds with data
//Because it doesn't want to block the entire code until it gets a response
console.log(data_json, 'Data Test - outside request code');
})
因此,假设您要使用第一个请求中的数据发出另一个请求-您将必须执行以下操作:
request('https://your-api.com/export-data.json', (err, res, body) => {
request('https://your-api.com/2nd-endpoint.json', err, res, body => {
//Process data and repeat
})
})
如您所见,该模式很快就会变得非常混乱-这被称为回调地狱,因此,为了避免产生大量嵌套请求,有一种语法糖可以使此代码看起来更加花哨和可维护,它是称为异步/等待模式。它是这样工作的:
let data_json = ''
app.get('/', async (req,res) => {
try{
let response = await request('https://your-api.com/endpoint')
data_json = response.body
} catch(error) {
//Handle error how you see fit
}
console.log(data_json) //It will work
})
此代码与您拥有的代码具有相同的作用,但是不同之处在于,您可以一次又一次地创建任意数量的await request(...)
,并且没有嵌套。唯一的区别是,您必须声明函数是异步async (req, res) => {...}
,并且所有let var = await request(...)
都必须嵌套在try-catch块中。这样,您就可以捕获错误。如果您认为有必要,可以将所有请求放在catch块中。
希望这有所帮助:)