【问题标题】:Restangular running onFulfilled callback on promise even when promise is rejected即使承诺被拒绝,Restangular 也会在承诺上运行 onFulfilled 回调
【发布时间】:2015-08-23 23:42:03
【问题描述】:

我正在将我的主题数据移动到一项服务并尝试对代码进行智能处理,但我遇到了一些问题。

当我关闭我的 API 服务器并运行 create 函数时,我希望只触发 onRejected 回调。而是 onFulfilledonRejected 回调都被触发了。

服务

(function(){
  'use strict';

  angular
  .module('app')
  .factory('$cmSubjectData', $cmSubjectData);

  function $cmSubjectData($log, Restangular, $mdToast) {

    var service = {
      getAll: getAll,
      getById: getById,
      update: update,
      create: create,
      destroy: destroy
    };

    return service;

    function getAll() {
      return subjects().getList().then(handleSuccess, handleError('Error getting all subjects'));
    }

    function getById(id) {
      return subjects().one(id).get().then(handleSuccess, handleError('Error getting this subject'));
    }

    function update(subject) {
      Restangular.all('subjects')
      .post(subject)
      .then(handleSuccess, handleError('Error updating subject'));
    }

    function create(subject) {
      Restangular.all('subjects')
      .post(subject)
      .then(successToast(subject.basicInfo.firstName + ' has been created'), handleError('Error creating subject'));
    }

    function destroy(id) {
      var subject = subjects().one(id);
      subject.remove()
      .then(successToast('Subject has been deleted!'), handleError('There was an error deleting this subject'));
    }

    // Private Functions
    function subjects() {
      return Restangular.service('subjects');
    }

    function handleSuccess(data) {
      $log.info('Success');
      return data;
    }

    function handleError(error) {
      return function () {
        $log.warn(error);
      };
    }

    function successToast(content) {
      $mdToast.show(
        $mdToast.simple()
        .content(content)
      );
    }

  }

})();

控制器

(function() {
  'use strict';

  angular
  .module('app')
  .controller('SubjectNewCtrl', SubjectNewCtrl);

  function SubjectNewCtrl($cmSubjectData) {

    var vm = this;

    vm.subject = {};
    vm.createSubject = $cmSubjectData.create;

  }

})();

查看函数调用的位置:

<button ng-click="vm.createSubject(vm.subject)">Add</button>

任何帮助将不胜感激。

【问题讨论】:

  • 你是否意识到,当你得到一个被拒绝的承诺并且它调用你的拒绝处理程序,然后你返回一个被拒绝的承诺以外的任何东西,结果的承诺得到了履行,而不是被拒绝? Promise 基础设施假设您在那个时候“处理”了 Promise,因此产生的 Promise 现在已经实现,而不是被拒绝。如果您没有拒绝处理程序,或者您返回一个被拒绝的承诺,或者您抛出拒绝处理程序,那么生成的承诺将被拒绝。因此,拒绝处理程序可以决定它想如何离开承诺。
  • 从今天开始查看此答案以获取类似信息:Promise.settle and promise fulfillment vs rejection
  • 如果在完成时,我运行 handleSuccess 函数,它按预期工作,但在运行 successToast 函数时,它不起作用。
  • 当您执行.then(successToast(...)) 时,您将立即运行successToast(...) 并将其返回值传递给.then(),这不是您想要的时间。请记住,如果您希望稍后执行,您必须将函数引用传递给.then()。您可以更改successToast() 以返回类似handleError() 的函数,也可以使用.then(function() { return successToast(...);})
  • 好的!所以我让successToast() 返回一个类似handleError() 的函数,所以它按预期工作(你想发布你的解决方案作为答案,以便我可以接受它作为正确答案吗?)。我不明白的是我认为successToast() 是一个函数,但现在我已经将它变成了一个函数内部的函数。所以我有点困惑。

标签: javascript angularjs restangular


【解决方案1】:

当你这样做时

.then(successToast(...))

您正在立即运行 successToast(...) 并将其返回值传递给 .then(),这不是您想要的时间。请记住,如果您希望稍后执行,您必须将函数引用传递给.then()。如果您在函数中包含括号 (),那么这会告诉 Javascript 立即执行您的函数。在这种情况下,这不是您想要的。如果你对函数没有额外的参数,你可以这样做:

.then(successToast)

但是,因为当你调用它时你有想要传递的参数,所以你不能那样做。所以,你有两个选择。你可以让它像handleError() 一样工作,使用参数调用它只会返回一个函数(所以这就是传递给.then() 的内容,如下所示:

function successToast(content) {
  return function() {
      $mdToast.show($mdToast.simple().content(content));
  }
}

然后,它会像你一样被调用:

.then(successToast(subject.basicInfo.firstName + ' has been created'))

或者您可以在调用本身中插入自己的存根函数引用:

.then(function() {
    return successToast(subject.basicInfo.firstName + ' has been created');
});

这两个示例都将函数引用传递给.then(),并且直到稍后.then() 调用该函数引用时才执行您的逻辑核心。

【讨论】:

    猜你喜欢
    • 2017-04-19
    • 1970-01-01
    • 2018-05-09
    • 2017-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2018-05-25
    • 2019-02-01
    相关资源
    最近更新 更多