最近开始认为是时候对我的逻辑操作进行大规模更新了,其中一部分是对Angular JS异步诺言调用的正确链接。给定以下代码,我如何将其重写为两个单独方法的正确链接? (是的,我已经看过其他有关此的文章,但是它们都处理了其他版本的Angular或其他语法,并且我正在寻找更新的内容。)
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;
}
);
}
);
从逻辑上讲,我的大脑告诉我应该可以执行以下操作:
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));
}
);
}
);
更新: 上方的“ api ....”调用调用了我的service.js层,其中的方法如下:
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);
});
},
根据Pop-A-Stash更新:
//#region Api Calls and Helper
function apiCallOne() {
return api.promise1({ Id: vm.Id });
}
function apiCallTwo() {
return api.promise2({param: vm.param });
}
function handleApiCallError(resultOrError, actionToSet, actionState) {
console.error(resultOrError);
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(resultOrError.statusText));
actionToSet = actionState;
}
//#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, vm.pgLoaded, true);
}
}
)
.catch(function(errorOne) { handleApiCallError(errorOne, vm.pgLoaded, true); });
}
init();
//#endregion
答案 0 :(得分:1)
如果要按特定顺序链接它们,则说明您已经正确执行了。但是我看到一些可以消除的代码重复:
vm.apiCallOne = apiCallOne;
vm.apiCallTwo = apiCallTwo;
vm.runChainedCalls = runChainedCalls;
function runChainedCalls() {
vm.processing = true;
vm.apiCallOne()
.then(function(result1) {
if(!result1.error) {
vm.apiCallTwo().then(function(result2) {
if(!result2.error) {
notificationService.success("<h5>Operation successful!.</h5>");
vm.data = result2.data;
vm.processing = false;
}
else {
handleError(result2);
}
})
.catch(function(errorTwo) {
handleError(errorTwo)
});
}
else {
handleError(result1);
}
})
.catch(function(errorOne) {
handleError(errorOne);
});
}
function apiCallOne(){
return api.callOne(param); //don't forget to return the promise object
};
function apiCallTwo() {
return api.callTwo(param); //don't forget to return the promise object
};
function handleError(resultOrError) {
notificationService.danger("<h5>An error occurred.</h5><h6>Details: {0}</h6>".format(resultOrError.statusText));
vm.processing = false;
}
您的控制器中的每个呼叫只需要一个.then()
和.catch()
。除此之外,还有代码重复。
如果要同时运行它们并且不关心顺序,则可以使用$q.all()
函数同时运行它们:
function runConcurrentCalls() {
$q.all([api.callOne(param), api.callTwo(param)]).then(function(responseArray) {
// responseArray contains array of both call responses
console.log(responseArray[0]);
console.log(responseArray[1]);
})
.catch(function() {
//something went wrong with one or both calls
});
}
答案 1 :(得分:1)
您可以使用递归来大大缩短代码,使用递归调用类似于以下内容的包含promise及其参数的对象数组:
function runPromises(promises) {
var first = promises.shift();
first.function(first.params).then(function(resp) {
if (promises.length > 1) {
runPromises(promises);
}
}).catch(function (error) {
handleError(error);
});
}
带有类似以下内容的初始数组:
var promises = [
{
function: promise1,
params: any
},
{
function: promise2,
params: any
}
];
如果每个promise响应都需要单独处理,则可以为每个promise解决promise后添加要触发的回调。