0

I've been trying to study on my own the basics of promises, async calls and how to chain them in AngularJS. Currently I'm maintaining an app that likes to use them everywhere, and as a novice they're really overwhelming to say the least.

First off, I have this code in the server-side (node.js) that retrieves a list of a manager's direct reports. This was how the previous dev did it, so I used it as a guide:

exports.findDirectReports = function (req, res) {
   var empnum = req.params.empnum;

   queries.getDirectReports(empnum)
       .then(function (users) {
           return res.json(users);
    })
    .catch(function (err) {
          handleError(res, err);
    });
};

What I understood (or thought I understood):

  1. queries.getDirectReports will execute first and return list as a promise.
  2. Resolved promise will be returned inside the then().
  3. return res.json(users) result will then be passed back to whoever called it to be used in other operations.

My problem is getting the resolved promise. I'm aware that I won't get the results right away since it's async. But I have a find() that uses these results as a condition, and everytime I check the results I always get null or [].

  1. Is there a way to get them immediately?
  2. If there are none, how can I execute my other function as soon as the results are ready?

Here's the function in question (also server-side node.js):

exports.downloadEmployee = function (req, res) {
     /* 
      "queries" - alias for another server-side node.js (not really sure what to call 
      this exactly) that contains the entire getDirectReports fxn.
    */

    queries.getDirectReports(empnum)
        .then(function (users) {
            EmployeeInfo.find({}, function (err, results) {
                var tempCtr = [];
                if (err) { return err; }

                /*
                    Use results of getDirectReports here as condition
                    where if employee exists, program will execute
                    _.forEach below.
                */

                _.forEach(results, function (item) {
                    tempCtr.push({
                        employeeID: item.employeeID,
                        employeeName: item.employeeName
                    });
                });
                return res.json(tempCtr);
            });
        })
        .catch(function (err) {
            handleError(res, err);
        });
}

I've seen somewhere here in SO that I need to take advantage of callbacks, but I don't really understand how. Some of the code samples were similar to the ones I've previously tried (but didn't work).

Any answers will be greatly appreciated.

Thank you.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Dee J.
  • 365
  • 4
  • 21
  • Possible duplicate of [Angular execution order with \`$q\`](http://stackoverflow.com/questions/34324153/angular-execution-order-with-q) – georgeawg Mar 28 '17 at 18:49
  • See also [AngularJS $q Service API Reference - Chaining Promises](https://docs.angularjs.org/api/ng/service/$q#chaining-promises). – georgeawg Mar 28 '17 at 19:27

1 Answers1

2

You need to return a promise from the function

exports.downloadEmployee = function (req, res) {
  return queries.getDirectReports(empnum)
    .then(function (users) {
      ...
      return res.json(user);
    })
    .catch(function (err) { ... });
}

Promises are async, so no there is no way to get this to resolve "immediately" and you will need to handle the resolution of the promise where this function is being called from.

AJ Funk
  • 3,099
  • 1
  • 16
  • 18
  • Hi, thanks for answering. I was under the impression that `return res.json(user);` means that my promises were already resolved, since they'll be thrown back to my client-side... I'll give this one a go! – Dee J. Mar 28 '17 at 07:12
  • Maybe I'm not understanding the problem. Are you having trouble getting the data on the client side? In your example above, the `res.json(user)` should still be executed but your promise will not be resolved (which is bad, but may not cause an error in this case). – AJ Funk Mar 28 '17 at 07:14
  • Nope, the `getDirectReports()` happens on the server-side. I can still get the `res.json(user)` results fine (and use them in my client-side with no probs), but like you said, my promise wasn't resolved yet. I added a `console.log` underneath `then(function (users) {` and got a `[]`. – Dee J. Mar 28 '17 at 07:22
  • 1
    If the code inside your `.then` is being executed, then the promise is being resolved. Since it's logging an empty array, this is more evidence that it is being resolved and a value is being returned (empty array). It's more likely that your `getDirectReports` function has an issue and is not finding any users so it is returning an empty array. – AJ Funk Mar 28 '17 at 07:25