Working with an AngularJS app (1.4.3), I want a controller to make a call to a method on a service, which should return a boolean value.
Under the hood, the service used to make a call to $window.confirm(), and then just return the result. I am trying to switch the implementation to use Angular Material's $mdDialog.confirm() API, but this returns a promise.
The problem I am running into is that there is no way to return true or false directly from my service without changing the code in my controller to expect a promise. The whole purpose of extracting this method into a service was so that the controller could be separated from the implementation details of the call, and I would consider using a promise (ie, a future boolean) vs. a straight boolean to be an implementation detail.
Here is some code to illustrate: In the controller:
function confirmDeleteDevice() {
if (notificationService.confirm('Are you sure you want to delete the device?')) {
deleteDevice();
}
}
Old function in 'notificationService':
function confirm(message) {
return $window.confirm(message);
}
New function in notificationService that will not work as expected with the controller code above:
function confirm(message) {
var confirm = $mdDialog.confirm()
.title(message)
.ariaLabel(message)
.ok('Yes')
.cancel('No');
return $mdDialog.show(confirm).then(function() {
return true;
}, function() {
return false;
});
}
Without changing the controller code to rely on the implementation detail of using a promise, how do I get a boolean value out of my service method? The code above will always execute "deleteDevice()" because the new notificationService.confirm() will return the unresolved promise, which apparently qualifies as a truthy value for the if clause.
I'm definitely no expert on promises, and I understand this isn't exactly how they are expected to be used, but I'd really rather not tie the controller down to using a promise. Is this even possible given the "async" nature of promises?
UPDATE: I definitely looked before I posted and could find nothing, but this just showed up in the "related questions" feed, so I see now my question was a duplicate. The answers there are pretty helpful.
Working with an AngularJS app (1.4.3), I want a controller to make a call to a method on a service, which should return a boolean value.
Under the hood, the service used to make a call to $window.confirm(), and then just return the result. I am trying to switch the implementation to use Angular Material's $mdDialog.confirm() API, but this returns a promise.
The problem I am running into is that there is no way to return true or false directly from my service without changing the code in my controller to expect a promise. The whole purpose of extracting this method into a service was so that the controller could be separated from the implementation details of the call, and I would consider using a promise (ie, a future boolean) vs. a straight boolean to be an implementation detail.
Here is some code to illustrate: In the controller:
function confirmDeleteDevice() {
if (notificationService.confirm('Are you sure you want to delete the device?')) {
deleteDevice();
}
}
Old function in 'notificationService':
function confirm(message) {
return $window.confirm(message);
}
New function in notificationService that will not work as expected with the controller code above:
function confirm(message) {
var confirm = $mdDialog.confirm()
.title(message)
.ariaLabel(message)
.ok('Yes')
.cancel('No');
return $mdDialog.show(confirm).then(function() {
return true;
}, function() {
return false;
});
}
Without changing the controller code to rely on the implementation detail of using a promise, how do I get a boolean value out of my service method? The code above will always execute "deleteDevice()" because the new notificationService.confirm() will return the unresolved promise, which apparently qualifies as a truthy value for the if clause.
I'm definitely no expert on promises, and I understand this isn't exactly how they are expected to be used, but I'd really rather not tie the controller down to using a promise. Is this even possible given the "async" nature of promises?
UPDATE: I definitely looked before I posted and could find nothing, but this just showed up in the "related questions" feed, so I see now my question was a duplicate. The answers there are pretty helpful.
Share Improve this question edited May 23, 2017 at 12:08 CommunityBot 11 silver badge asked Sep 4, 2015 at 19:20 SeanSean 4981 gold badge5 silver badges13 bronze badges 1- 1 No, asynchrony is not an implementation detail, as it does change the control flow of the caller a lot. And no, there's no way to get the boolean out of the promise synchronously. Just make your controller expect asynchronous results - and you can make it an implementation detail that its synchronous under the hood. – Bergi Commented Sep 4, 2015 at 22:03
1 Answer
Reset to default 2You will have to make your condition async as well, chaining through the promise.
i.e
notificationService.confirm('...').then(function(confirmation){
if(confirmation) {
deleteDevice();
}
});
and you really would not need to have catch and return false
unless you need to really track the return value since dialog already resolves/rejects the promise based on cancel or Ok, i.e below blocks wont be needed.
.then(function() {
return true;
}, function() {
return false;
});
So
function confirm(message) {
var confirm = $mdDialog.confirm()
.title(message)
.ariaLabel(message)
.ok('Yes')
.cancel('No');
return $mdDialog.show(confirm);
}
and just:
notificationService.confirm('...').then(deleteDevice);