0

The code below works for me

Promise.all([first, second, third]).then([first, second, third] => {
  console.log(second);
});

I know that console.log(second) will give me the value with the key second.

My promises are dynamically set and now it looks like below:

let collection = [second, third];

Promise.all(collection).then((collection) => {
  console.log(collection);
});
  • In this example I set two values in collection. In real life it can include more or less values.
  • When I use console.log(collection) it will output collection[0] and collection[1]. In this case I don't know what which value collection[1] is.

Question

How can I, like my first example, have something like named dynamically arguments like collection['second'] or similar?

Jens Törnell
  • 23,180
  • 45
  • 124
  • 206
  • My collections always include an identifier, since I want collections to be portable. So they should not rely on either the request or response object that fetched the collection to know what they are. Since the promises retain their order, worst case you can keep a list of what's inside `let collection` and map the names back to the responses once the `.all()` resolves. – Shilly Jan 28 '20 at 14:15

2 Answers2

2

As we want to access the value dynamically, set collection to an empty object first. Then, use the keys from collection to pass all its Promise-values to Promise.all. Then, map back the fulfilled values and then, we can access collection's value by some key.

let collection = {}

for (let i = 0; i < 3; i++) {
  collection[`key${i}`] = Promise.resolve(i)
}

let collectionKeys = Object.keys(collection)
Promise.all(collectionKeys.map(key => collection[key]))
  .then(values => {
    let collectionFulfilled = collectionKeys.reduce((obj, key, i) => {
      obj[key] = values[i]
      return obj
    }, {})
    console.log(collectionFulfilled)
  })
Richard
  • 7,037
  • 2
  • 23
  • 76
  • Yes, that worked great! You don't like to put `;` at the end of the lines do you? ;) – Jens Törnell Jan 28 '20 at 14:40
  • @JensTörnell https://stackoverflow.com/questions/2846283/what-are-the-rules-for-javascripts-automatic-semicolon-insertion-asi/2846298#2846298 personally I like putting `;` , but some people like ASI. – Keith Jan 28 '20 at 14:42
  • @JensTörnell I used to use `;`. Since I learnt Kotlin (that does not allow semicolon), I decided that it just *looks better* (if that makes sense?) without a semicolon, so yeah no semicolon xD – Richard Jan 28 '20 at 14:47
  • @Keith I see. I just noticed that my Vscode automatically add `;` if they are missing. I guess it's the PrettierNow extension that does it. – Jens Törnell Jan 28 '20 at 14:51
1

If you pass your promises embedded inside an object with a single key, you could use that for it's name, and then with a simple helper function reverse the values & keys from this.

With the new ES6 you can then just pass like -> [{one}, {two}, {three}] etc.

Below is an example with a helper function called namedPromiseAll.

function namedPromiseAll(named) {
  const pcollection =
    named.map(m => Object.values(m)[0]);
  const ncollection =
    named.map(m => Object.keys(m)[0]);
  return Promise.all(pcollection).then((c) => {
    return c.reduce((a,v,ix) => {
      a[ncollection[ix]] = v;
      return a;
    }, {});
  });
}


const second = Promise.resolve(2);
const third = Promise.resolve(3);

const collection = [{second}, {third}];

namedPromiseAll(collection).then(console.log);
Keith
  • 22,005
  • 2
  • 27
  • 44