0

I am trying to replace an instance of hardcoding in a web application with 2 very similar API calls, as I don't have time to rewrite a whole new procedure and endpoint to handle the same functionality right now. I am able to get the data from the 2 individual calls fine with Promise.all. But the template for this page (it is using handlebars) is expecting a single object to loop through and display the options in a drop down.

I have been trying to use spread operators to bring the contents of the results together with no duplicates, and it does work as expected if I mock it up synchronously in the console, but in practice the results get nested into another object as if it were an array.

This is the code actually running:

Promise.all([
        this.isUsers = GetUsersByRole("Inside Sales", app.user.id),
        this.asmUsers = GetUsersByRole("Area Sales Managers", app.user.id)
    ]).then((is, asm) => {
        // is and asm contain the correct data here, I just want to merge it
        this.users = {...is, ...asm};
        var dummy = {...is, ...asm};
        console.log("dummy", dummy);
    });

In the console, manually copying the data from each successful data grab into its own object and then combining with the spread operator as above gives the expected result. But this code returns some sort of nesting of it instead:

console log of the dummy object which contains two separate objects instead of the merged contents of the api call results

If the spread operator (or using Object.attach, which I have also tried) worked as expected, I believe I would have the result I'm looking for. I don't know how many little hacks I've tried to merge the objects properly, but none seem to have the right behavior in this context.

I may just need some more reading on Promises and async operations, so feel free to link me

EDIT

Destructuring the results of the Promise with array brackets like so:

Promise.all([
        this.isUsers = GetUsersByRole("Inside Sales", app.user.id),
        this.asmUsers = GetUsersByRole("Area Sales Managers", app.user.id)
    ]).then(([is, asm]) => {
        this.users = {...is, ...asm};
        var dummy = {...is, ...asm};
        console.log("Dummy", dummy);
    });

...leaves the dummy object completely empty as far as I can tell: empty dummy object

Trying to spread the data objects with square brackets:

var dummy = [...is, ...asm];

Results in a type error, as they as Objects:

Uncaught (in promise) TypeError: is is not iterable

EDIT

Thank you to everyone for their help, I had to convert the function I was using to make the api calls to return a Promise and then the code worked as expected

  • 1
    It should be `([is, asm]) =>`, not `(is, asm) =>`. You want to destructure the array returned by Promise.all. – kelsny Sep 29 '22 at 18:39
  • @caTS I just tried this again, but then I get nothing in any objects in output and the drop down sees nothing. Not sure if this related to this using backbone.js I believe – Walter Tracey Sep 29 '22 at 18:44
  • Well, rest assured that this is the correct way. Try to confirm this by logging `this.users` or something. If you think this is a backbone.js problem, insert the relevant code that demonstrates the problem. – kelsny Sep 29 '22 at 18:45
  • @WalterTracey Try `console.log(is, asm)`. They are probably not what you think they are. – Unmitigated Sep 29 '22 at 18:46
  • @Unmitigated Printing them in that block shows that they are each a single object with the data I want, it's just putting them together that creates odd behavior – Walter Tracey Sep 29 '22 at 18:49
  • What are the property names in the two objects? – Barmar Sep 29 '22 at 19:03
  • @Barmar The two data objects have guids as keys mapping to readable names as values. The templating file uses them to display the names and makes a new call using their id for their data when you choose them – Walter Tracey Sep 29 '22 at 19:05
  • 1
    The console output you show is from before you fixed `(is, asm)` to `([is, asm])`, right? Show the output after that fix. – Barmar Sep 29 '22 at 19:12
  • @Barmar Then `dummy` prints as an empty object. That doesn't really "fix" anything, although I'm not saying it's not part of the solution – Walter Tracey Sep 29 '22 at 19:19
  • What does `console.log(JSON.stringify(is), JSON.stringify(asm))` show? – Barmar Sep 29 '22 at 19:21
  • @Barmar `[{},{}] undefined`, which is definitely interesting I will grant you that. The array part seems to come from printing them that way, separated by commas, though. When I print it without the stringify, they still have the correct data in them – Walter Tracey Sep 29 '22 at 19:31
  • That looks like what I would expect with `(is, asm) =>` instead of `([is, asm]) =>`. But you said you fixed that. – Barmar Sep 29 '22 at 19:41
  • Please edit the question and show the current version of the code. – Barmar Sep 29 '22 at 19:41
  • @Barmar When I destructure that way, then dummy is a completely empty object. If I do `var dummy = [...is, ...asm]` as if they are arrays, again, I get `Uncaught (in promise) TypeError: is is not iterable`, presumably because they are not arrays – Walter Tracey Sep 29 '22 at 19:50
  • Are you sure that `getUsersByRole` returns a promise? Now I suspect it's returning an object that it's updating asynchronously. – Barmar Sep 29 '22 at 19:53
  • @Barmar I believe you are correct. In that case, how would I make the two api calls and put that data together synchronously? – Walter Tracey Sep 29 '22 at 20:00
  • 1
    Assuming it takes a callback function, see https://stackoverflow.com/questions/22519784/how-do-i-convert-an-existing-callback-api-to-promises for how to convert it to a promise. – Barmar Sep 29 '22 at 20:01
  • 1
    @Barmar Thank you for the link I'm reading into it. I am almost positive part of my problem is just Promise misunderstanding – Walter Tracey Sep 29 '22 at 20:06

0 Answers0