0

I'm writing a service method that will return a promise to get an object from an API. The object is returned with an array of links to get child objects from the API as well. The key here is that I don't want the outer promise to resolve until all of the child objects have been retrieved and added to the parent MyType. The following is CLOSE to what I want, but I don't know how to get the promise to wait for the child objects to be resolved before returning.

private getRegistrationDetailsPromise(url: string): Promise<MyType> {    
  return new Promise<MyType>((resolve) => {
     return this.dataService.GetMyType(url)
       .then((myType: MyType) => {                    
          _.forEach(myType.childReferences, function(childUrl) {
            let child = this.dataService.GetChild(childUrl).then((child) -> {
                myType.children.push(child);
            };
        };                  
        return (x);
    });
});
Steve Wash
  • 986
  • 4
  • 23
  • 50
  • 2
    You already have a promise; you should not call `new Promise()`. – SLaks Aug 16 '17 at 00:57
  • Was going to offer you a finished code solution that uses `Promise.all()` to wait on your loop of promises, but I can't really understand the details of what you're trying to do. You also have an anti-pattern when you're wrapping internal promises with `new Promise()`. You don't need to do that either. You can just return inner promises to chain things and use `Promise.all()` to wait on multiple promises. – jfriend00 Aug 16 '17 at 02:55
  • 1
    Also, why in the age of ES6 and ES7 are people still using `_.forEach()` which is about the most inefficient way to iterate an array possible. In this case, you should probably use `myType.childReferences.map()` to accumulate an array of child promises which can be passed to `Promise.all()` and then returned from the inner `.then()` handler. – jfriend00 Aug 16 '17 at 02:57
  • 1
    Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Aug 16 '17 at 04:24
  • @jfriend00 I'd guess that `_.forEach(arr, …)` is still faster than `arr.forEach(…)` - but yes, `map` should always be preferred. – Bergi Aug 16 '17 at 04:25
  • Something is wrong with your indentation and/or parenthesis – Bergi Aug 16 '17 at 04:27
  • @Bergi - As we've discussed before `for/of` is favored over plain `array.forEach()` anyway. I just don't understand why people continue to use third party libraries for things that there are multiple native built-in implementations for. – jfriend00 Aug 16 '17 at 04:27

1 Answers1

2

Change _.forEach to .map(), and return the nested promise from the callback.
That will give you an array of promises.

You can then pass that array to Promise.all() to get a promise that waits for all of them.

Finally, you'll want to return that promise from your promise chain.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Thanks, everyone for their help. This makes sense to me now. Also, I don't code in Typescript frequently and haven't kept up with ES6/ES7 changes. Gives me something else to work on, which is good. – Steve Wash Aug 16 '17 at 12:53