【问题标题】:Chaining AngularJS Promises in controller. Is this workaround valid?在控制器中链接 AngularJS Promises。这种解决方法有效吗?
【发布时间】:2015-12-02 20:31:06
【问题描述】:

注意:这是在 TypeScript / Angular 1.4.x 中

javascript 中的插件:http://plnkr.co/edit/LCka4CFLcRe0lPEF9AM2?p=preview

我必须用 Promise 链接多个调用。 init3 依赖于 init2 依赖于 init1

有些承诺即使失败也需要继续。所以我不得不在这里使用扁平化技术:http://solutionoptimist.com/2013/12/27/javascript-promise-chains-2/ 来重用回调代码。

问题是在链接承诺时,我在第一个链中完全丢失了控制器的 this 实例(init2init3) 所以我修改了内部返回以传递链中的控制器,以便可以访问绑定(绑定到控制器)和服务。

这是有效/正确的吗? (传递链中的控制器并为成功/错误重用相同的回调)

代码中的注释也解释/提出问题。

代码:

export class ControllerX {

    private myInformation: string;
    private myMoreInformation: string;

    public constructor(private $q: ng.IQService, private service1: Service1) {

        this.init()
            .then(this.init2) //If init() fails dont continue the chain
            .then(this.init3, this.init3); //Even if init2() fail, we continue.
            //init2() cannot fail now but its a recovery example.
    }

    private init(): ng.IPromise<ControllerX> {
        return this.service1.getMyInformation().then((information: string): ControllerX => {
            this.myInformation = information;
            return this; //Push this for the next then
        }); //Do nothing on error, let it propagate.
    }

    private init2(ctrl?: ControllerX): ng.IPromise<ControllerX> {

        if (!ctrl) { //Are we called from a chain
            ctrl = this;
        }

        return ctrl.service1.getMyMoreInfo().then((information: string): ControllerX => {
            ctrl.myMoreInformation = information;
            return ctrl;
        }, (error: any): ControleurListeCours => {
            ctrl.myMoreInformation = DEFAULT;
            return ctrl;
        });
    }

    private init3(ctrl?: ControllerX): ng.IPromise<ControllerX> {
        //blablabla
    }
}

【问题讨论】:

  • 我的情况不同。第一次调用 init() 实际上是一个粗箭头等价物。这在那里工作得很好。然后我在第二次松开“这个”。 (链式的,init2 和 init3)这就是为什么我必须开始返回链式 promise 中的控制器作为参数。
  • 我返回“this”,因此 init2 可以接收控制器作为参数。 (承诺链)我没有找到任何其他方式来访问 init2 中的控制器。

标签: angularjs controller promise chaining


【解决方案1】:

此代码不会按预期工作。

 this.init()
        .then(this.init2) //If init() fails dont continue the chain
        .then(this.init3, this.init3); //Even if init2() fail, we continue.
        //init2() cannot fail now but its a recovery example.

如果init失败,代码将跳过init2,但会被第二个then方法捕获,并执行init3

HTML

<div ng-app="myApp" ng-controller="myVm as vm">
  <pre>
init1 status = {{vm.init1Status}}
init2 status = {{vm.init2Status}}
init3 status = {{vm.init3Status}}
  </pre>
</div>

JS

angular.module('myApp',[]).controller('myVm', function ($q) {
    var vm = this;
    vm.init1Status = "not done";
    vm.init2Status = "not done";
    vm.init3Status = "not done";

    function init1() {
      vm.init1Status = "init1 failed";
      return $q.reject("init1 failed");
    };

    function init2() {
      vm.init2Status = "init2 done";
    };

    function init3() {
      vm.init3Status = "init3 done";
    };

    init1().then(init2).then(init3,init3);
});

结果

init1 status = init1 failed
init2 status = not done
init3 status = init3 done

JSFiddle

【讨论】:

  • @georgeawd 您好,感谢您的回答。我做了一些测试,发现了这个问题。所以我修改了我的案例,所以当我想停止链条时,我返回拒绝。现在它看起来更像这样,但最初的想法仍然有效且有效:init1().then(init2, stop).then(init3,stop).then(stop); function stop(ctrl) { ctrl.loading=false; $q.reject(); }
  • @georgeawd 我也看到在纯 JS 中,你没有我在 TypeScript 中遇到的问题。我在 plunker 上的版本是从 TypeScript 编译生成的 JavaScript。如果您调试,您会看到在 init2 内部,上下文丢失了。修改 Fiddle 以更好地管理链。 :link
  • 有时 Plnkr 已关闭,所以这是 Fiddle 中的 TypeScript 编译版本。控制台显示this 问题。
猜你喜欢
  • 2012-05-16
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多