我使用请求来调用一个API,它在一个名为body的对象中为我提供电影数据,但是当我试图将它传递给一个数组并控制台记录它时,终端显示给我一个空数组。
let copy = [];
const request = require('request');
request('https://www.omdbapi.com/?t=JOKER&apikey=b04f2804', { json: true }, (err, res, body) => {
if (err) { return console.log(err);}
copy.push(JSON.parse(JSON.stringify(body)))
});
console.log(copy);
首先,不推荐使用request()
库编写新代码。这里有一个备选方案列表(它们都支持承诺)。
其次,request()
库是非阻塞和异步的。这意味着当您调用request()
时,它开始操作,然后立即返回。调用request()
之后的代码在request()
调用它的回调之前继续执行。因此,您试图在数组的值被设置之前检查它。这是异步编程中的一个经典问题。有很多方法可以处理这个问题。如果你继续使用request()
库,那么你必须要么在回调本身内部使用结果,要么你可以在回调中调用其他函数并将数组传递给它。
对于列出的所有支持承诺的替代库之一(我最喜欢的是got()
库),您可以使用await
,这通常是异步操作的首选编程风格:
const got = require('got');
async function someFunction() {
let result = await got('https://www.omdbapi.com/?t=JOKER&apikey=b04f2804').json();
// you can use the result here
console.log(result);
// Or you can return it and it will become the resolved value
// of the promise this async function returns
return result;
}
someFunction().then(result => {
// can use result here
}).catch(err => {
console.log(err);
});
请注意,当您在执行copy.push()
时将异步检索的数据写入更高作用域的变量时,这通常是一个警告,表明您正在做一些错误的事情。这是因为高级作用域中的任何代码都不会知道该变量中的数据何时可用。在极少数情况下,您可能会这样做(比如实现缓存),但这些情况必须是数据存储仅供将来参考,而不是立即使用的情况。99.9%的情况下,当我们看到这种结构时,这是一种错误的使用异步检索数据的编程方式。