Как откатить изменения при ошибке в цепочке промисов

В моем угловом приложении я хочу внести изменения в несколько мест в моей firebase с помощью сочетания транзакций и set. Я написал цепочку обещаний с небольшая помощь. Теперь мне нужно обработать любые ошибки, которые могут возникнуть.

В случае ошибки на любом из обещаний я хотел бы отменить любые изменения, сделанные в firebase (успешные обещания), и предупредить пользователя о сбое.

Текущий код ниже

$scope.addNewPost = function() {
  var refPosts = new Firebase(FBURL).child('/posts').push();
  // Get tags into array for incrementing counters
  var tags = $scope.post.tags.split(', ');
  var allPromises = [];
  // Iterate through tags and set promises for transactions to increment tag count
  angular.forEach(tags, function(value, index){
    var dfd = $q.defer();
    var refTag = new Firebase(FBURL).child('/tags/' + value);
    refTag.transaction( function (current_value) {
      return current_value + 1;
    }, function(error, committed, snapshot) {
      if (committed) {
        dfd.resolve( snapshot );
      } else {
        dfd.reject( error );
      }
    });
    allPromises.push( dfd.promise );
  });

  // Add promise for setting the post data
  var dfd = $q.defer();
  refPosts.set( $scope.post, function (error) {
    if (error) {
      dfd.reject(error);
    } else {
      dfd.resolve('post recorded');
    }
  });
  allPromises.push( dfd.promise );

  $q.all( allPromises ).then(
    function () {
      $scope.reset(); // or redirect to post
    },
    function (error) {
      // error handling goes here how would I
      // roll back any data written to firebase
      alert('Error: something went wrong your post has not been created.');
    }
  );
};

Итак, что мне нужно знать, так это то, как мне откатить любые изменения, которые происходят с моими данными Firebase, в случае, если одно из этих обещаний не выполняется. В firebase может происходить любое количество обновлений. (например: 3 тега увеличиваются с помощью транзакции и устанавливаются данные публикации)

Как мне написать функцию отказа, чтобы вычислить, что было успешным, и отменить это? Если это вообще возможно.

--------------- вопрос из исходного сообщения решен ---------------

Кроме того, как вы заставляете ошибки? Я попытался установить переменную, как показано ниже, но, похоже, она не работает. Что-то не так с моим .then?

refPosts.set( $scope.post, function (error) {
  var forceError = true;
  if (forceError) {
    dfd.reject(forceError);
  } else {
    dfd.resolve('post recorded');
  }
  allPromises.push( dfd.promise );
});

person Tg7z    schedule 31.12.2013    source источник
comment
Я пытаюсь сделать то же самое (создание блога angular-firebase с тегами статей, которые можно фильтровать). Вы когда-нибудь понимали это?   -  person Omid Ahourai    schedule 03.04.2015


Ответы (1)


Есть два экземпляра этой строки, и они оба не в том месте:

allPromises.push( dfd.promise );
  • В первом блоке он должен быть в последнем операторе обратного вызова forEach, а не в обратном вызове транзакции.
  • Во втором блоке он должен быть после вызова set(), а не в обратном вызове.

То, как ваш код написан сейчас, $q.all() получает пустой массив промисов. Это также может мешать тесту forceError, который вы пытаетесь выполнить.

person paulmelnikow    schedule 31.12.2013
comment
Спасибо Ноа, что позволяет мне вызвать ошибку. Это было немного в стороне и определенно было проблемой, но это была только часть того, о чем я спрашивал. Я редактирую сообщение, чтобы более четко определить вопрос. - person Tg7z; 31.12.2013