简体   繁体   English

数组推送导致空数组javascript

[英]array push results in empty array javascript

I am trying to store API results into an array. 我正在尝试将API结果存储到数组中。

The data is displayed in console, but on pushing the data into an array, the array is still empty. 数据显示在控制台中,但在将数据推入数组时,数组仍为空。

Here's the code: 这是代码:

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

It looks like you're defining the favorites array within the scope of the function callback. 看起来您正在函数回调范围内定义favorites数组。 Try putting var favorites = []; 尝试把var favorites = []; above you app.post() call instead. app.post()之上调用。

Also, keep in mind that it will only have a value after the callback is complete, so any synchronous code later down the line will only see the empty array value. 另外,请记住,在回调完成后它只会有一个值,因此后面的任何同步代码只会看到空数组值。

I've updated your code to get favorites by storing separately the promise and call it afterwards: 我已经更新了你的代码,通过单独存储承诺并随后调用它来获取收藏:

UPDATE UPDATE

As you can see in the demo, i have 2x console.log at the bottom, the first one( C1 ) is contained in the promise favoritesPromise () and the second ( C2 ) is after the promise. 正如你在演示中看到的那样,我在底部有2x console.log,第一个( C1 )包含在promise favoritesPromise () ,第二个( C2 )包含在promise之后。 Synchronous actions will never wait for asynchronus actions to take place, therefore in my example C2 will always be outputted before C1 , even if console.log(1 ... ) is before console.log(2 ... ), they'll appear reversed in the console. 同步操作永远不会等待异步操作发生,因此在我的示例中, C2将始终在C1之前输出,即使console.log(1 ...)在console.log(2 ...)之前,它们也会在控制台中出现反转。

In the promise i added a setTimeout of 1ms to mock a request, it was all it took to achieve the current output. 在promise中我添加了1ms的setTimeout来模拟一个请求,它只需要实现当前输出。 Another thing you can test is removing the setTimeout then output will change a bit, your promise becomes synchronus until it reaches resolve(favorites) , that means favorites has all the data by now, but when resolve takes place, it becomes async, and in your console you will still see C2 first (but now with data) and C1 second. 你可以测试的另一件事是删除setTimeout然后输出会改变一点,你的promise会变成同步,直到它达到resolve(favorites) ,这意味着favorites现在拥有所有数据,但是当resolve发生时,它变为异步,并且你的控制台你仍然会首先看到C2 (但现在有数据)和C1秒。

In my earlier answer i tried to implement this reasoning to your code. 在我之前的回答中,我试图对你的代码实现这种推理。 Keep it async folks! 保持它不同步的人!

 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); 

 app.post('/fetchFavoriteTweets/', verifyToken, function(req, res) {


  const favoritesPromise = () => {

    return new Promise((resolve, reject) => {

      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) reject(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);
                  reject(err);

                }

              });

              resolve(data);

            });
            console.log(favorites);
            // res.status(200).json({msg:'success', data:favorites});
          }
        });
      }).catch(function(e) {
        reject(e)
      })

    });

  }


  // Here you call the promise to retrieve "favorites"
  favoritesPromise().then(favoritesList => {

    console.log('your favorites array', favoritesList)

  })


})

Try next code 尝试下一个代码

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM