2015-12-02 64 views
0

注:這是打字稿/角的1.4.x鏈接AngularJS控制器中的承諾。此解決方法是否有效?

Plunker在javascript:http://plnkr.co/edit/LCka4CFLcRe0lPEF9AM2?p=preview

我不得不鏈多次調用與承諾。 init3取決於init2取決於init1

一些承諾即使失敗也需要繼續。所以我不得不在這裏使用扁平化技術:http://solutionoptimist.com/2013/12/27/javascript-promise-chains-2/重用回調代碼。

問題是,當鏈接的承諾,我完全失去第一個鏈,然後(init2init3)內部控制的this例如 所以我修改內部收益通過控制器鏈使綁定(綁定到控制器)和服務是可訪問的。

這是有效/正確嗎? (通過鏈中的控制器並重復使用相同的回調來獲得成功/錯誤)

代碼中的註釋也解釋/提出問題。

代碼:

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 
    } 
} 
+0

我的情況有所不同。第一次調用init()實際上是一個等價的胖箭頭。這是完美的工作。然後我在第二次放鬆「這個」。 (鏈接的一個,init2和init3)這就是爲什麼我必須開始在鏈式承諾中返回控制器作爲參數。 – Rouche

+0

我返回「this」,因此init2可以接收控制器作爲參數。 (承諾鏈)我沒有找到任何其他方式來訪問init2中的控制器。 – Rouche

回答

0

預期該代碼將無法正常工作。

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

+0

@georgeawd嗨,謝謝你的回答。我做了一些測試,看到了這個問題。所以我修改我的情況,所以當我想停止鏈條時,我返回一個拒絕。現在它看起來更像這樣,但最初的想法仍然有效並且正在工作:'init1()。then(init2,stop).then(init3,stop).then(stop);函數停止(ctrl){ctrl.loading = false; $ q.reject(); }' – Rouche

+0

@georgeawd我也看到在純JS中,你沒有我在TypeScript中遇到的問題。我在plunker上的版本是從TypeScript編譯生成的JavaScript。如果你調試了,你會在init2裏看到上下文丟失了。修改小提琴以更好地管理鏈條。 :[鏈接](http:// jsfiddle。net/mmp7923s/7 /) – Rouche

+0

有時Plnkr已關閉,因此這是[Fiddle](http://jsfiddle.net/mmp7923s/13/)中的TypeScript編譯版本。控制檯顯示「這個」問題。 – Rouche