是否可以將承諾傳遞給來自外部控制器(例如觸發該狀態的控制器)的UI.Router $state
?將承諾傳遞給Angular-UI狀態控制器
我知道$state.go()
返回一個承諾;
是否可以用您自己的承諾覆蓋該內容
直接自行解決此承諾或使用新承諾解決此承諾?
此外,文件說,通過$state.go()
返回的承諾,可以與其他承諾(由transition superseded
表示)被拒絕,但我到處都找不到,指示如何從國家自身內完成。
例如,在下面的代碼,我希望能夠等待用戶繼續到doSomethingElse()
之前,點擊一個按鈕($scope.buttonClicked()
)。
我知道我可以發出一個事件,但由於承諾被烘烤到角度如此之深,我想知道是否有辦法通過promise.resolve
/promise.reject
這樣做。
angular.module('APP', ['ui.router'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('myState', {
template: '<p>myState</p>',
controller: ['$state', '$scope', '$q', function ($state, $scope, $q) {
var deferred = $q.defer();
$scope.buttonClicked = function() {
deferred.resolve();
}
}]
});
}])
.controller('mainCtrl', ['$state', function ($state) {
$state.go('myState')
.then(doSomethingElse)
}]);
更新 我已經接受了@ blint的答案,因爲它已得到最接近我我想要的東西。下面是一些代碼,更豐富地回答了這個答案的想法。我不認爲我寫這篇文章的方式是一個非常優雅的解決方案,如果有人能夠提出更好的解決觸發狀態承諾的方法,我很高興。
我選擇的解決方案是按照通常在控制器中的方式鏈接您的承諾,但請附上一個$scope.next()
方法(或類似的方法)來解決/拒絕承諾。由於狀態可以繼承調用控制器的作用域,因此它將能夠直接調用該方法,從而解決/拒絕承諾。下面是它如何工作的:
首先,設置你的狀態的按鈕/那叫一個$scope.next()
方法控制器:
.config(function ($stateProvider) {
$stateProvider
.state('selectLanguage', {
template: '<p>Select language for app: \
<select ng-model="user.language" ng-options="language.label for language in languages">\
<option value="">Please select</option>\
</select>\
<button ng-click="next()">Next</button>\
</p>',
controller: function ($scope) {
$scope.languages = [
{label: 'Deutch', value: 'de'},
{label: 'English', value: 'en'},
{label: 'Français', value: 'fr'},
{label: 'Error', value: null}
];
}
})
.state('getUserInfo', {
template: '<p>Name: <input ng-model="user.name" /><br />\
Email: <input ng-model="user.email" /><br />\
<button ng-click="next()">Next</button>\
</p>'
})
.state('mainMenu', {
template: '<p>The main menu for {{user.name}} is in {{user.language.label}}</p>'
})
.state('error', {
template: '<p>There was an error</p>'
});
})
接下來,您設置控制器。在這種情況下,我使用本地服務方法user.loadFromLocalStorage()
來讓球滾動(它返回一個承諾),但是任何承諾都會執行。在此工作流程中,如果$scope.user
缺少任何內容,它將逐漸使用狀態填充。如果它已完全填充,則會跳到主菜單的右側。如果元素爲空或處於無效狀態,則會進入錯誤視圖。
.controller('mainCtrl', function ($scope, $state, $q, User) {
$scope.user = new User();
$scope.user.loadFromLocalStorage()
.then(function() {
var deferred;
if ($scope.user.language === null) {
deferred = $q.defer();
$state.go('selectLanguage');
$scope.next = function() {
$scope.next = undefined;
if ($scope.user.language === null) {
return deferred.reject('Language not selected somehow');
}
deferred.resolve();
};
return deferred.promise;
}
})
.then(function() {
var deferred;
if ($scope.user.name === null || $scope.user.email === null) {
deferred = $q.defer();
$state.go('getUserInfo');
$scope.next = function() {
$scope.next = undefined;
if ($scope.user.name === null || $scope.user.email === null) {
return deferred.reject('Could not get user name or email');
}
deferred.resolve();
};
return deferred.promise;
}
})
.then(function() {
$state.go('mainMenu');
})
.catch(function (err) {
$state.go('error', err);
});
});
這是相當詳細的,還不是非常乾燥,但它顯示了使用承諾異步流控制的總體意圖。
你是什麼意思?是否有可能用你自己的承諾來重寫?'? – blint
對不起。我想更好的方式是,你可以用你自己的承諾來解決一個「$ state」的承諾。 – Andrew