0

I am using only ES6 and no libraries, like Bluebird or Async. I also do not want to use async/await.

Here is the side effect code:

function getManager(name) {
   return new Promise(resolve => {
       resolve({
          id: 123,
          location: 'San Diego'
       });
   });
}

function getEmployees(managerId) {
   return new Promise(resolve => {
       resolve([
          {
              id: 321,
              name: 'Jack'
              location: 'Detroit'
          },
          {
              id: 456,
              name: 'Jill'
              location: 'Cleveland'
          }
       ]);
   });
}

var manager;
getManager('Bob').then(function (result) {
  manager = result;
  return getEmployees(manager.id);
}).then(function (employees) {
  // okay, I have both the "manager" and the "employess"
});

And here is the Pass-thru Variable:

function getManager(name) {
   return new Promise(resolve => {
       resolve({
          id: 123,
          location: 'San Diego'
       });
   });
}

function getEmployees(manager) {
   return new Promise(resolve => {
       resolve({
          employees: [
              {
                  id: 321,
                  name: 'Jack'
                  location: 'Detroit'
              },
              {
                  id: 456,
                  name: 'Jill'
                  location: 'Cleveland'
              }
          ],
          manager: manager
       });
   });
}

getManager('Bob').then(function (result) {
  manager = result;
  return getEmployees(manager);
}).then(function (results) {
  // okay, I have both the "results.manager" and the "results.employess"
});

Are there other ways to handle variables in promise-chaining? Are there downsides to using side effect code? Side effect seems a little more straight forward.

Matt Kuhns
  • 1,328
  • 1
  • 13
  • 26
  • 3
    I'm just wondering why you don't want to use async/await? – djheru Apr 24 '19 at 19:54
  • I'm wondering the same thing, given how much shorter and more readable it is: https://jsfiddle.net/khrismuc/z8vuk56m/ –  Apr 24 '19 at 19:58
  • Use async/await if you could. Also there are more options. For example `const bob = getManager('Bob'); const bobEmployees = bob.then(manager => getEmployees(manager.id)); Promise.all([bob, bobEmployees]).then(([bob, employees]) => { /**/})` – Yury Tarabanko Apr 24 '19 at 19:59
  • Exact duplicate of [How do I access previous promise results in a `.then()` chain?](https://stackoverflow.com/q/28250680/1048572) – Bergi Apr 30 '19 at 04:23

3 Answers3

1

Pass-Thru is better

The reason that the pass-thru technique is better is that it does the following:

  1. It allows you to use those functions multiple times without overriding a global variable and ending up with the wrong value.
  2. You can use those functions and pass those promises around regardless of any global variable definitions (or even local ones).
  3. Avoiding global variables makes your code cleaner and easier to reason about.
  4. Makes the manager a part of your return type, granting better intellisense.
Andria
  • 4,712
  • 2
  • 22
  • 38
1

I would suggest a hybrid solution:

  • The side-effects of the first solution (mutating a global variable) are to be avoided
  • Adapting the function getEmployees to solve a problem that is not in that function itself seems not right either.

You can use Promise.all to combine a previous result with a current result. This way you have the best of both alternatives:

function getManager(name) {
    return Promise.resolve({
        id: 123,
        location: 'San Diego'
    });
}

function getEmployees(manager) {
    return Promise.resolve([{
        id: 321,
        name: 'Jack',
        location: 'Detroit'
    }, {
        id: 456,
        name: 'Jill',
        location: 'Cleveland'
    }]);
}

getManager('Bob').then(function (manager) {
    return Promise.all([manager, getEmployees(manager)]);
}).then(function ([manager, employees]) {
    console.log(manager.location, employees.map(({name})=>name).join());
});
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Yes, I hadn't thought of it this way. I usually use Promise.all when the results are not dependent on each other. – Matt Kuhns Apr 24 '19 at 20:19
0

I know you said you don't want to use async/await, but this is what it would look like if you did:

async function main() {
  const manager = await getManager('Bob');
  const employees = await getEmployees(manager);
  console.log(manager, employees);
}
djheru
  • 3,525
  • 2
  • 20
  • 20