Recently started thinking that it was time to do a massive update to my logical operations, and part of that is the proper chaining of Angular JS asynchronous promise calls. Given the following code, how would I re-write it to be a proper chaining of two separate methods? (Yes, I've seen other posts about this, but they all deal with other versions of Angular, or other syntaxes, and I'm looking for something more up-to-date.)
vm.functionName = (
function() {
vm.processing = true;
api.promise1({ Id: vm.Id })
.then(
function(result) {
if (result.error) {
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(result.error));
} else {
api.promise2({ param: vm.param })
.then(
function(result2) {
if (result2.error) {
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(result2.error));
} else {
vm.data = result2.data;
notificationService.success("<h5>Operation successful!.</h5>");
}
vm.processing = false;
}
)
.catch(
function (err) {
console.error(err);
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(err.statusText));
vm.processing = false;
}
);
}
}
)
.catch(
function (err) {
console.error(err);
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(err.statusText));
vm.processing = false;
}
);
}
);
Logically, my brain tells me that I should be able to do something like this:
vm.functionName = (
function() {
vm.processing = true;
vm.promise1()
.then(
vm.promise2()
.then(
notificationService.success("<h5>Operation successful!.</h5>");
vm.processing = false;
);
);
);
}
);
vm.promise1 = (
function() {
api.promise1({ Id: vm.Id })
.then(
function(result) {
if (result.error) {
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(result.error));
}
}
)
.catch(
function (err) {
console.error(err);
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(err.statusText));
}
);
}
);
vm.promise2 = (
function() {
api.promise2({ param: vm.param })
.then(
function(result) {
if (result.error) {
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(result.error));
} else {
vm.data = result2.data;
}
}
)
.catch(
function (err) {
console.error(err);
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(err.statusText));
}
);
}
);
Update: the "api...." calls above call to my service.js layer, where methods exist like such:
promise1: function (params, error) {
return $http
.post("/C#Controller/Method1", params)
.then(handleSuccess)
.catch(function (e) {
handleError(e, error);
});
},
promise2: function (params, error) {
return $http
.post("/C#Controller/Method2", params)
.then(handleSuccess)
.catch(function (e) {
handleError(e, error);
});
},
Updated, per Pop-A-Stash's ideas, as now implemented:
//#region Api Calls and Helper
function apiCallOne() {
return api.promise1({ Id: vm.Id });
}
function apiCallTwo() {
return api.promise2({param: vm.param });
}
function handleApiCallError(resultOrError, ngModelToSet) {
var errMsg = resultOrError.statusText === undefined ? resultOrError.error === undefined ? "Unknown Error" : resultOrError.error : resultOrError.statusText;
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(errMsg));
//This allows updating things like variables and ng-model goodies, via an inset function.
if (ngModelToSet) {
ngModelToSet();
}
}
//#endregion
//#region Initialization
function init() {
vm.pgLoaded = false;
apiCallOne()
.then(
function(result) {
if (!result.error) {
vm.data = result.data;
vm.pgLoaded = true;
} else {
handleApiCallError(result, function() { vm.pgLoaded = true; });
}
}
)
.catch(function(errorOne) { handleApiCallError(errorOne, function() { vm.pgLoaded = true; }); });
}
init();
//#endregion