0

Firstly I appreciate that there are many answers out there explaining this topic but I just can't understand it at the moment.

I want to loop through a JavaScript object I have created and then perform various actions like making a request to an API and then storing some data in Redis.

This is what I have so far

const params = { "handle1": { "screen_name": "handle1", "hash_tag": "#hashtag1"},
             "handle2": { "screen_name": "handle2", "hash_tag": "#hashtag2"} }

for (const k of Object.keys(params)) {
  console.log("Searching for " + params[k]['screen_name'])

  client.get('statuses/user_timeline', { screen_name: params[k]['screen_name']})
  .then(function (tweets) {

    for (const key of Object.keys(tweets)) {
      const val = tweets[key]['text'];

      if(val.includes(params[k]['hash_tag'])) {
        console.log("Found")
        r_client.hset(params[k]['screen_name'], 'tweet_id', tweets[key]['id'], 'tweet_text', tweets[key]['text'], function (err, res) {
          console.log(res)
        });
        r_client.hgetall(params[k]['screen_name'], function(err, object) {
          console.log(object);
        });
     }
   }
   r_client.quit();
  })
  .catch(function (error) {
    throw error;
  });
}

When I run this the output is as follows

Searching for handle1
Searching for handle2
Found
0
{ tweet_id: '123456789',
  tweet_text: 'text found in tweet' }
Found
undefined
undefined

So straight away I have a problem in that the first loop hasn't event finished and it's moved onto the second loop.

I would like to run this in sequential order (if that's the best way), but more importantly I was hoping someone could break down my code and explain how I should be approaching this to have it run correctly.

halfer
  • 19,824
  • 17
  • 99
  • 186
Richlewis
  • 15,070
  • 37
  • 122
  • 283
  • The second loop is inside the definition of the first. If you need to run one then another consider putting them side by side. – evolutionxbox Mar 21 '18 at 14:28
  • Rich, your questions are a bit noisy for a 7K user. We trim out "thanks" and "help appreciated" - you have 317 instances of the latter, which is a lot of work for volunteer editors. Please also refrain from giving voting advice - if people think your question is worth voting one way or the other, they will. Don't paint a target on your back. – halfer Mar 21 '18 at 14:38
  • @halfer apologies, did not realise you guys did that. Always thought politeness went a long way, though no problem if these kind of civilities are unnecessary. Will refrain from doing this in the future – Richlewis Mar 21 '18 at 14:43
  • Yep, a technical standard of writing is preferred here. References [here](https://meta.stackoverflow.com/q/260776) and [here](https://meta.stackoverflow.com/q/288160), and there's probably others lurking on _Meta_! – halfer Mar 21 '18 at 15:05

2 Answers2

0

const tweets = await client.get(...) should do the trick.

Gabriel Bleu
  • 9,703
  • 2
  • 30
  • 43
0

Under the condition that .get(), .hset() and hgetall() return Promises this should pause the execution until all functions have resolved:

const params = {
  "handle1": {
    "screen_name": "handle1",
    "hash_tag": "#hashtag1"
  },
  "handle2": {
    "screen_name": "handle2",
    "hash_tag": "#hashtag2"
  }
}
async function search(params) {
  for (const k in params) { //for..in goes through the keys
    console.log("Searching for " + params[k]['screen_name'])

    const tweets = await client.get('statuses/user_timeline', {
      screen_name: params[k]['screen_name']
    });

    for (const key in tweets) { //same loop
      const val = tweets[key]['text'];

      if (val.includes(params[k]['hash_tag'])) {
        console.log("Found")
        await r_client.hset(params[k]['screen_name'], 'tweet_id', tweets[key]['id'], 'tweet_text', tweets[key]['text'], (err, res) => {
          console.log(res)
        });
        await r_client.hgetall(params[k]['screen_name'], (err, object) => {
          console.log(object);
        });
      }
    }
    r_client.quit();
  }
}

search(params);
Sebastian Speitel
  • 7,166
  • 2
  • 19
  • 38