Как правильно связать асинхронные вызовы AngularJS (AngularJs 1.7.5) - PullRequest
0 голосов
/ 20 июня 2019

Недавно начал думать, что пришло время массово обновить мои логические операции, и отчасти это является правильной цепочкой вызовов асинхронных обещаний 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);
        });
},

Обновлено, за каждую копилку:

//#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 ]

1 голос
/ 21 июня 2019

Вы можете значительно сократить свой код, используя рекурсию, чтобы вызвать следующее обещание в массиве объектов, содержащих обещания и их параметры, используя нечто похожее на это:

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
      }
    ];

Если для каждого ответа на обещание требуется индивидуальная обработка, вы можете добавить обратный вызов, который будет запущен после того, как обещание разрешено для каждого обещания.

1 голос
/ 20 июня 2019

Если вы хотите связать их в определенном порядке, то вы уже делаете это правильно.Однако я вижу некоторое дублирование кода, которое может быть устранено:

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
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...