Примечание: это в TypeScript/Angular 1.4.x
Plunker в javascript: http://plnkr.co/edit/LCka4CFLcRe0lPEF9AM2?p=preview
Мне нужно объединить несколько вызовов с обещаниями. init3
зависит от init2
зависит от init1
.
Некоторые из обещаний необходимо продолжить, даже если они потерпят неудачу. Поэтому мне пришлось использовать сплющенную технику здесь: http://solutionoptimist.com/2013/12/27/javascript-promise-chains-2/ Для повторного использования кода обратного вызова.
Проблема в том, что когда цепочка обещает, я полностью теряю контроллер this
экземпляра внутри 1-й цепи (init2
и init3
). Поэтому я изменил внутренний возврат, чтобы передать контроллер в цепочке, чтобы привязки (привязка к контроллеру) и сервисы были доступны.
Действительно ли это/правильно? (передача контроллера в цепочку и повторное использование обратного вызова для успеха/ошибки)
Комментарии в коде также объясняют/задают вопросы.
Код:
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
}
}
Этот код не будет работать должным образом.
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
init1().then(init2, stop).then(init3,stop).then(stop); function stop(ctrl) { ctrl.loading=false; $q.reject(); }