如何:正确链接AngularJS异步调用(AngularJs 1.7.5)

时间:2019-06-20 16:09:54

标签: javascript angularjs

最近开始认为是时候对我的逻辑操作进行大规模更新了,其中一部分是对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

2 个答案:

答案 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后添加要触发的回调。