简体   繁体   中英

array push results in empty array javascript

I am trying to store API results into an array.

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. Try putting var favorites = []; above you app.post() call instead.

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

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. 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.

In the promise i added a setTimeout of 1ms to mock a request, it was all it took to achieve the current output. 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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