2015-12-22 49 views
1

我有一個AngularJs應用程序並使用RXJS。我有一個等待用戶允許或拒絕訪問一個OAuth服務提供商,擁有這個簽名服務:如何在angularJs應用程序中刷新視圖onError調用Observable主題

authorise(requestDetails : IRequestDetails) : Rx.Observable<string>; 

當訪問是允許的,我讓我的訪問令牌後,我通過這回像控制器此:

request.observable.onNext(request.access_token); 
request.observable.onCompleted(); 

,並通過更新背襯變量用於消息傳遞這個回視圖控制器:

private _message : string = "Awaiting authorisation"; 

    get message() : string { 
     return this._message; 
    } 

    authenticate() : void 
    { 
     this._oAuthService.authorise(Example.googleAuthDetails).subscribe(
      (result : string) => this.handleAuthorisation(result), 
      (fault : string) => this.handleError(fault) 
     ); 
    } 

    private handleAuthorisation(result : string) : void { 
     this._message = result; 
    } 

這一切工作正常。我發現它在這種情況下起作用的原因是因爲onNext調用是作爲$ http調用結果的一部分進行的。這個調用被包裝在$ apply的調用中,觸發一個摘要循環。 然而,當用戶拒絕訪問我打電話的onError上觀察到:

request.observable.onError("access token denied"); 
    request.observable.onCompleted(); 

,並在控制器我更新錯誤的字符串:

private handleError(fault : string) : void { 
     this._message = fault; 
    } 

但在這種情況下,視圖不會更新和顯示的字符串保持爲「正在等待授權」。 在這種情況下,由於授權被拒絕,所以沒有進行$ http調用,並且控制器被觸發的函數未包含在$ apply調用中。

我在我的html頁面中包含了rx.angular.js庫,希望能夠自動修復它,但是它沒有。閱讀文檔似乎我可能不得不專門看某些東西。我認爲我可以讓它與RXJS一起工作,並且在某些更新時總是更新範圍。 我不想將範圍注入到控制器中,如果不需要,可以強制更新。我不喜歡有依賴。

整個項目可查看在該分支:

https://github.com/Roaders/Typescript-OAuth-SPA/blob/rxjs_issues/index.html

回答

0

,它沒有對錯誤的情況下工作的原因是因爲沒有HTTP調用觸發消化週期所以我們需要在這種情況下觸發摘要循環。

爲此,我們需要將$ rootScope注入到服務中,當我們調用onError時,我們需要將它包裝在$ rootScope中。$套用來電:

 this._scope.$apply(() => { 
      request.observable.onError("access token denied"); 
      request.observable.onCompleted(); 
     }); 

該解決方案是在這裏: https://github.com/Roaders/Typescript-OAuth-SPA/tree/rx_solved_with_scope

我知道,我說我不想一個範圍內注射,但現在我有一個更好的理解爲什麼我需要,我想我我很好。我也很樂意注入根作用域而不是其他控制器作用域。

0

只是包裝一切都變成$timeout調用,它將確保摘要被調用。

RX.angular看起來不錯,但我認爲這是有點過時的新準則,不要使用$scope無處不在。

var myAppModule = angular.module('myApp', []).controller('ctrl', SettingsController1); 
 

 
function SettingsController1($timeout) { 
 

 
    this.message = "waiting"; 
 
    this.observable = new Rx.ReplaySubject(2 /* buffer size */); 
 
    var _this = this; 
 
    this.observable.subscribe(
 
    function(x) { 
 
     $timeout(function() { 
 
     _this.message = x; 
 
     }, 0); 
 
    }, 
 
    function(err) { 
 
     $timeout(function() { 
 
     _this.message = err; 
 
     }, 0); 
 
    }, 
 
    function() { 
 
     this.message = 'completed'; 
 
    }); 
 

 
    this.success = function() { 
 
    this.observable.onNext('success'); 
 
    } 
 

 
    this.error = function() { 
 
    this.observable.onError('failed'); 
 
    } 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.all.min.js"></script> 
 

 
<div ng-app="myApp" ng-controller="ctrl as ctrl"> 
 
    <div> 
 
    {{ ctrl.message }} 
 
    </div> 
 
    <button ng-click="ctrl.success()"> 
 
    Success 
 
    </button> 
 
    <button ng-click="ctrl.error()"> 
 
    Error 
 
    </button> 
 
</div>

該解決方案在該分支實現:https://github.com/Roaders/Typescript-OAuth-SPA/tree/rx_solved_with_timeout

+0

這樣做的工作感謝,但它似乎有點混亂的解決方案。我並不是真的想要在每次超時回調時都打包,或者需要在每個地方都注入超時值。 有沒有人有更好的/整潔的解決方案。 現在接受這個答案,但會接受來的任何整潔的人。 – Roaders

+0

是的,這是不理想的,angular2將解決這種事情,如果它可以讓你更快樂:) –

相關問題