我正在尝试将API结果存储到数组中。
数据显示在控制台中,但是将数据推入数组时,该数组仍然为空。
代码如下:
app.post('/fetchFavoriteTweets/', verifyToken, function(req, res) {
var favorites = [];
dbConn.then( function (database) {
var dbo = database.db("twitter_search");
dbo.collection('users').findOne(
{ _id: ObjectId(req.userId) }, function(err, result) {
if(err) throw err;
if(!result.hasOwnProperty('favorite_tweets')) {
res.status(404).json({msg:'record not found'});
}
else {
result.favorite_tweets.forEach(function (tweet) {
T.get('statuses/show', {id: tweet.id}, function(err, data, response) {
if(!err){
favorites.push(data);
console.log(data); //this returns data
} else {
console.log(err);
}
});
});
console.log(favorites);
// res.status(200).json({msg:'success', data:favorites});
}
});
}).catch(function(e){console.log(e)})
});
答案 0 :(得分:2)
似乎您正在函数回调范围内定义favorites
数组。尝试将var favorites = [];
置于您的app.post()
通话上方。
此外,请记住,只有在回调完成后它才会有一个值,因此该行之后的所有同步代码将仅看到空数组值。
答案 1 :(得分:1)
我已经更新了您的代码,以通过分别存储promise并随后调用它来获得收藏夹:
更新
如您在演示中所见,我在底部有2x console.log,第一个( C1 )包含在promise favoritesPromise ()
中,第二个( > C2 )。
同步操作永远不会等待异步操作发生,因此,在我的示例中,即使console.log(1 ...)是 C2 ,也总是在 C1 之前输出。在console.log(2 ...)之前,它们将在控制台中以相反的方式出现。
在承诺中,我添加了一个1ms的setTimeout
来模拟请求,这是实现当前输出所需要的全部。您可以测试的另一件事是删除setTimeout
,然后输出将有所变化,您的承诺将变为同步,直到达到resolve(favorites)
,这意味着favorites
到现在为止已经拥有所有数据,但是当{ {1}}发生,它变得异步,并且在控制台中,您仍然会首先看到 C2 (但现在有数据),然后看到 C1 。
在我先前的回答中,我试图对您的代码实施这种推理。 保持异步状态!
resolve
var favorites = [];
var favoritesPromise = () => {
return new Promise((resolve, reject) => {
console.log('Retrieving data from the internet.');
// This timeout mocks your request to anything that is async or promie
setTimeout(() => {
console.log('Request done')
let resultFavorite_tweets = [{
id: 1,
name: 'a dog'
}, {
id: 2,
name: 'a cat'
}];
resultFavorite_tweets.forEach(item => {
favorites.push(item.name);
})
resolve(favorites);
// if you have an error use
// reject(err)
}, 1);
});
}
favoritesPromise().then(favList => {
console.log(1, 'this will always contain data from the internet, but will always be last', favList);
})
console.log(2, 'this will be empty (unless you remove setTimeout), but will always be first', favorites);
答案 2 :(得分:1)
尝试下一个代码
app.post('/fetchFavoriteTweets/', verifyToken, function (req, res) {
var favorites = [];
dbConn.then(function (database) {
var dbo = database.db("twitter_search");
dbo.collection('users').findOne(
{ _id: ObjectId(req.userId) }, function (err, result) {
if (err) throw err;
if (!result.hasOwnProperty('favorite_tweets')) {
res.status(404).json({ msg: 'record not found' });
}
else {
// Counter
let count = result.favorite_tweets.length;
result.favorite_tweets.forEach(function (tweet) {
T.get('statuses/show', { id: tweet.id }, function (err, data, response) {
// Decrease count
count -= 1;
if (!err) {
favorites.push(data);
// Check if count is zero
if (count === 0) {
console.log(favorites);
res.status(200).json({msg:'success', data:favorites});
}
} else {
console.log(err);
}
});
});
}
});
}).catch(function (e) { console.log(e) })
});