数组推送导致空数组javascript

时间:2018-10-03 16:55:07

标签: javascript node.js rest api

我正在尝试将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)})
});

3 个答案:

答案 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) })
});