4

I've an object like;

{ '6': { stream: { twitch: [Object] } },
  '7': { stream: { twitch: [Object] } },
  '8': { stream: { twitch: [Object] } },
  '9': { stream: { twitch: [Object] } },
  '10': { stream: { twitch: [Object] } },
  '11': { stream: { twitch: [Object] } } }

I want to iterate over it like;

return Promise.map(myObj, function(minute, minuteIndex) {

so basically minute should hold the data and minuteIndex should be holding the index.

I can do it with lodash but bluebird can't somehow.

_.forEach(hour.minutes, function(minute, minuteIndex) {

I know that this code was working before but now can't get it so.

Any ideas?

HuseyinUslu
  • 4,094
  • 5
  • 33
  • 50
  • Why is that an object with numbers for keys? Maybe you should use an array instead? – Tomalak Dec 05 '16 at 10:23
  • I can't. This is a special structure to hold per-minute stastistics of data over mongoose. I need those indexes. – HuseyinUslu Dec 05 '16 at 10:25
  • 1
    I don't understand. An array has numbers as keys. You want numbers as keys. Logical conclusion: Use an array. – Tomalak Dec 05 '16 at 10:26
  • Nah that could be only a javascript object; http://stackoverflow.com/a/1144737/170181 - which is already what I'm using as. – HuseyinUslu Dec 05 '16 at 10:28

4 Answers4

5

You can map the object's keys into an array and give that to Promise.map():

function process(stats) {
    var statsArray = Object.keys(stats).map(key => ({
        minute: key, minuteIndex: stats[key]
    }));
    return Promise.map(statsArray, item => {
        // work with item.minute & item.minuteIndex
    });
}

Usage:

var twitchStats = {
  '6': { stream: { twitch: [Object] } },
  '7': { stream: { twitch: [Object] } },
  '8': { stream: { twitch: [Object] } },
  '9': { stream: { twitch: [Object] } },
  '10': { stream: { twitch: [Object] } },
  '11': { stream: { twitch: [Object] } }
};

process(twitchStats).then(result => {
    // ...
});
Tomalak
  • 332,285
  • 67
  • 532
  • 628
2
Promise.all(

  Object.keys(twitchStats).map(key => Promise.resolve({
        minute: key, minuteIndex: twitchStats[key]
    })

)

Use combination of Promise.all() with map() functions. Be careful: map() has to return promise in order for Promise.all() work.

Chad Johnson
  • 21,215
  • 34
  • 109
  • 207
RepiatX
  • 95
  • 1
  • 8
0

You can also convert the object to an array, using _.toPairs, then you should be able to use the Promise.map methods.

alexvicegrab
  • 531
  • 3
  • 18
0

You don't specify in your question if you are using the Promise.map() callback to return a promise or a value. If you only want to return a value, there is not much benefit to using Promise.map() over forEach.

Bluebird's Promise.map() used for it's most basic interface is according to the docs:

to replace the .push+Promise.all boilerplate

Assuming you want to return promises, you can use lodash.map() to iterate over the object and have the key available when creating the promise, then use Promise.all() to execute them.

  let jobs =
    _.map(myObj, (minute, minuteIndex) => {
      return fnThatReturnsPromise(minute, minuteIndex);
    });

  return Promise.all(jobs);

Or as a single statement that more closely resembles your desired format

  return Promise.all(_.map(myObj, (minute, minuteIndex) => {
    return fnThatReturnsPromise(minute, minuteIndex);
  }));
MrMaz
  • 31
  • 4