2016-11-21 74 views
0

我已經返回,如果用戶當前已登錄在解決一個承諾,或等待解決,一旦用戶已經登錄,這樣你就可以做到這一點的函數...Angular promise .then()重複?

myService.waitForLogin().then(function(){ 
    // Subscribe to pusher.com events 
}); 

然後我用類似的調用來在用戶註銷時取消訂閱事件。

麻煩的是,我希望每次在用戶登錄時運行我。然後()的代碼,所以這個過程是....

  • 如果用戶登錄,運行代碼。

  • 如果不是,請等到他們登錄後再運行代碼。

  • 如果他們註銷然後又回來,再次運行代碼。

我最初使用$ rootscope。$上聽登入/註銷這對於重複出現行之有效的活動,但我需要它是基於在用戶已經登錄的情況下的諾言。

這裏是我的代碼:

var defer = $q.defer(); 

if(isLoggedIn()){ 
    defer.resolve(); 
} 

else{ 

    var offLoggedInTrue = $rootScope.$on('loggedin-true', function(){ 
     defer.resolve(); 
     offLoggedInTrue(); 
    }); 

} 

return defer.promise; 
+1

承諾只能得到按定義解決一次......。也許你應該嘗試使用其他異步系統,如'Rx.Observable'(儘管這是一個完全不同的API) – olivarra1

+0

或者如果用戶已經登錄,你可以手動觸發'loggedin-true'事件。 – sniels

+0

我不確定這是否是可能的與rxjs。基本上,是的,這是可能的,但我們都知道,'window.setTimeout'具有最大限制。還要記住移動瀏覽器問題,由於安全性和GUI凍結原因,沒有實現'window.setTimeout'。但是你可以在一段時間內合理地發出事件,這會檢查用戶是否登錄。或者更好:改變你的概念。還有很多其他的方法來完成這個共同的任務。也許你可以使用REST請求到你的後端來定期檢索用戶狀態。 – alpham8

回答

1

您可以通過存儲推遲對你的服務使用承諾CONTROLL登錄狀態,然後通過你的方法waitForLogin()返回的承諾。但是,您可以通知它,而不是解決承諾,一旦解決了登錄承諾,它就不會再被解決,因此您可以多次重複使用它。

注意:這是一個使用承諾的解決方案,但是您可能會發現更好的使用事件,在我看來這更容易維護。

例如:

angular.module('myApp', []) 
    .service('LoginStatusService', function($q) { 

    // store a deferred to represent the login resolution state 
    var loginDeferred = $q.defer(); 

    // the getter method to yout login promise 
    this.waitForLogin = function() { 
     return loginDeferred.promise; 
    }; 

    // an example login method from where you could notify the login promise 
    this.login = function(login, password) { 
     /// do async login things and then 
     loginDeferred.notify(); 
    }; 

    // when the deferred may need to got reseted 
    this.logoff = function(login, password) { 
     /// do logoff things and then 
     // loginPromise = $q.defer(); 
    }; 
    }) 

那麼你的控制器或任何供應商,你想,你可以注入的服務,並使用它,像這樣的:

.controller('MyController', function(LoginStatusService) { 

    LoginStatusService.waitForLogin().then(null, null, function() { 
     // do your subscribe stuff here 
    }); 
    }); 
+0

謝謝,但如果我沒有弄錯,這仍然只會觸發一次,不是嗎? – jonhobbs

+0

@jonhobbs是的,我已經更新了我的答案,而不是使用'resolve',你可以使用'notify'。這可能會幫助你解決這個問題。 –

+0

謝謝,我認爲這是我應該接受的答案,但是我對使用無限期通知以及永不解決或拒絕承諾感到有點不舒服。你能看到這樣做的任何副作用嗎?是否應該在某個時候被迫解決/拒絕? – jonhobbs

1

您可以繼續使用「的loggedIn真「,並且在訂閱事件後,如果用戶已經登錄,則可以手動觸發事件。以下是一個小例子。

angular.module('app', []) 
 
    .controller("mainController", function($scope, $rootScope) { 
 
    $scope.output = ""; 
 
    $rootScope.$on('loggedin-true', function() { 
 
     $scope.output += "loggedin event \n"; 
 
    }); 
 
    if (isLoggedIn()) { 
 
     $rootScope.$emit("loggedin-true"); 
 
    } 
 
    logOut($scope); 
 
    logIn($scope, $rootScope); 
 
    }); 
 

 
function isLoggedIn() { 
 
    return true; 
 
} 
 

 
function logOut($scope) { 
 
    $scope.output += "loggedout \n"; 
 
} 
 

 
function logIn($scope, $rootScope) { 
 
    $scope.output += "login \n"; 
 
    //login successfull 
 
    $rootScope.$emit("loggedin-true"); 
 
}
<div ng-app="app" ng-controller="mainController"> 
 
    <pre>{{output}}<pre> 
 
</div> 
 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

+0

感謝Sniels,我想我已經知道我可以做很長的路,但我希望這個功能易於使用,並且我想讓它保持乾爽,因爲其他開發人員將會調用我的waitForLogin()函數,並且我不會不希望他們每次都寫很多邏輯。但感謝您的答案。 – jonhobbs

+0

如果你想讓它乾燥,我建議把它放在一個服務中,並將它注入你的控制器。我不喜歡在服務中使用範圍,但我不會爲EventEmitter邏輯提供一個庫,因爲它已經在Angular中。這是[一篇博文](http://www.codelord.net/2015/05/04/angularjs-notifying-about-changes-from-services-to-controllers/)如何將其包裝到服務中。 – sniels