3

I'm fairly new to Javascript promises, and running into an issue that I can't hunt down anything about via Google or Stack Exchange. When I refer to a function in a .then chained off a promise, I sometimes have to wrap that function in an anonymous function in order to stop it from automatically executing before the original promise is resolved. For example, if my code is

function deleteAdvertiser(advertiser) {
    dialogService.Confirm(null, 'Delete')
        .then(advertiserService.deleteAdvertiser(advertiser))
        .then(getAdvertisers);
}

the call to advertiserService.deleteAdvertiser will automatically fire before I resolve the promise from the dialogService.Confirm. However, if I write it as

function deleteAdvertiser(advertiser) {
    dialogService.Confirm(null, 'Delete')
        .then(function () {
            advertiserService.deleteAdvertiser(advertiser)
                .then(getAdvertisers);
            });
}

it behaves as expected: the advertiserService.deleteAdvertiser call doesn't happen until I resolve the dialogService.Confirm promise (in this case by clicking the "Delete" button inside my confirmation dialog).

The dialogService uses ngDialog's .openConfirm method, which returns a promise. I've verified that this promise is returning correctly. My best guess as to why this is happening is that my need to pass along an advertiser object from the UI (the function is initially called via an ng-click on a trash can button) means that I have to call advertiserService.deleteAdvertiser(advertiser)-- that is to say, with an argument passed in-- which in turn means that JS is executing that function call as soon as it reads it, rather than just storing the reference to use later when the initial promise is resolved.

Am I correct in my understanding of why the first code block doesn't work? Why does wrapping it in an anonymous function make the difference? And is there a correct (or at least better) way to chain these promises?

Thank you!

nwebb
  • 33
  • 2
  • Well, you wouldn't do `.then(getAdvertisers())` either, would you? – Bergi May 13 '15 at 15:16
  • I wouldn't, but I'm not sure how else to do what I need to do, calling advertiserService.deleteAdvertiser(advertiser) with the argument passing through. – nwebb May 13 '15 at 15:19

1 Answers1

4

with an argument passed in, JS is executing that function call as soon as it reads it

Yes. When you pass an argument, and put () behind the function, you are calling it. You need to pass a function instead - just like you do .then(getAdvertisers) instead of .then(getAdvertisers()).

Notice that it doesn't need to be a function expression, you could use .bind as well:

dialogService.Confirm(null, 'Delete')
    .then(advertiserService.deleteAdvertiser.bind(advertiserService, advertiser))
    .then(getAdvertisers);

which is roughly equivalent to

dialogService.Confirm(null, 'Delete')
    .then(function(confirmRes) {
        return advertiserService.deleteAdvertiser(advertiser);
    })
    .then(getAdvertisers);
Bergi
  • 630,263
  • 148
  • 957
  • 1,375