В чем разница между этими двумя синтаксисами

Если бы у меня был

promise = userService.updateUser($stateParams.userId, req);

promise.then(
    function(user) {
        logger.logSuccess('Updated user');
        $scope.resetForm();
        WizardHandler.wizard().goTo(0);
        return user;
    }, 
    function(error) {
        logger.logError('Ups an error has occurred');
        console.error('error updating user: ' + error);
    }
); 

promise.then(function(user) {
    _.each(uploader.getNotUploadedItems(), function(item) {
        return item.formData.push({
            id: user.id
        });
    });
});

Затем, если updateUser терпит неудачу, журнал будет показан, а затем второй then не будет выполнен, однако, если у меня есть

promise = userService.updateUser($stateParams.userId, req).then(
    function(user) {
        logger.logSuccess('Updated user');
        $scope.resetForm();
        WizardHandler.wizard().goTo(0);
        return user;
    }, 
    function(error) {
        logger.logError('Ups an error has occurred');
        console.error('error updating user: ' + error);
    }
); 

promise.then(function(user) {
    _.each(uploader.getNotUploadedItems(), function(item) {
        return item.formData.push({
            id: user.id
        });
    });
});

Затем будет выполнен второй

Я не могу понять, почему, я имею в виду, разве это не просто обычная цепочка?


person forcewill    schedule 23.03.2015    source источник


Ответы (1)


если updateUser терпит неудачу, журнал будет показан, а затем второй, а затем не будет выполнен

Да, потому что вы разветвляетесь:

              success: - logSuccessAndResetForm()
               |       - makeNewFormData()
updateUser() --+
  promise      |
              error    - logError()

но при использовании обычной цепочки будет выполнена вторая цепочка

Да, конечно. Ваш обработчик ошибок обрабатывает ошибку, и promise выполняется с возвращаемым значением.

              success: - logSuccessAndResetForm()           success: - makeNewFormData()
               |                               \             |
updateUser() --+                                >- promise --+
               |                               /             |
              error    - logError()           ´             error:   (nothing)

См. также этот ответ, чтобы увидеть более красивые схемы управления аналогичным кодом.

person Bergi    schedule 23.03.2015
comment
Сноска для тех, кто пытается следовать этому: то, что говорит Берги, верно для нативных обещаний js и большинства основных библиотек обещаний. Но будьте внимательны к обещаниям jQuery, которые ведут себя иначе. В jQuery обработчик ошибок .then помечает подчиненное обещание как обработанное только если оно явно возвращает отклоненное обещание. Естественным поведением является распространение состояния ошибки. Таким образом, ни одна из версий кода в вопросе не запустит второй обработчик успеха. Также обратите внимание, что разработчики jQuery, вероятно, нормализуют это поведение в какой-то момент в будущем. - person Roamer-1888; 23.03.2015
comment
@Roamer-1888: Это не единственная их проблема, но на самом деле я не хочу связывать этот пост с каждым вопрос с обещанием. Отложенные jQuery не являются правильными обещаниями, точка :-) - person Bergi; 23.03.2015
comment
Берги, согласен, нельзя каждый раз предлагать оговорку jQuery. Но ваши диаграммы делают этот ответ очень ясным и убедительным - его, вероятно, прочитают многие люди. - person Roamer-1888; 23.03.2015
comment
Честно говоря, они исправляют это, на самом деле они объединили исправление со своей основной веткой всего несколько дней назад, а в версии 3.0, которая выйдет в ближайшее время, проблема исправлена, а также проблемы со временем :) - person Benjamin Gruenbaum; 24.03.2015
comment
@Bergi .then() возвращает другое обещание, а не исходное обещание? что это, я думаю, мне нужно больше читать об обещаниях, чтобы полностью понять их - person forcewill; 25.03.2015
comment
@forcewill: Да, это так. На самом деле суть обещаний :-) - person Bergi; 25.03.2015