javascript - 将 promise 传递给 Angular-UI 状态 Controller

标签 javascript angularjs promise angular-ui angular-ui-router

是否可以从外部 Controller (例如触发状态的 Controller )向 UI.Router $state 传递 promise ?

我知道 $state.go() 返回一个 promise ;是否可以用你自己的 promise 覆盖它自己直接解决这个 promise 或使用新的 promise 解决它?

另外,文档说 $state.go() 返回的 promise 可以被另一个 promise 拒绝(由 transition superseded 表示),但我不能找到表明如何从国家内部完成此操作的任何地方。

例如,在下面的代码中,我希望能够等待用户点击按钮 ($scope.buttonClicked()),然后再继续 doSomethingElse ()

我知道我可以发出一个事件,但由于 promises 在 Angular 中的根基如此之深,我想知道是否有办法通过 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 的回答,因为它让我最接近我想要的。下面是一些代码,可以进一步充实这个答案的想法。我不认为我写这篇文章的方式是一个非常优雅的解决方案,如果有人可以提出更好的方法来解决触发状态的 promise ,我很高兴。

我选择的解决方案是像往常一样在 Controller 中链接您的 promise ,但将 $scope.next() 方法(或类似的方法)附加到解析的范围/拒绝 promise 。由于状态可以继承调用 Controller 的作用域,它将能够直接调用该方法,从而解决/拒绝 promise 。以下是它的工作原理:

首先,使用调用 $scope.next() 方法的按钮/ Controller 设置状态:

.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>'
    });
})

接下来,您将设置您的 Controller 。在这种情况下,我使用本地服务方法 user.loadFromLocalStorage() 来启动(它返回一个 promise ),但任何 promise 都可以。在此工作流程中,如果 $scope.user 缺少任何内容,它将逐渐使用状态填充。如果它已完全填充,它会直接跳到主菜单。如果元素留空或处于无效状态,您将进入错误 View 。

.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);
    });

});

这很冗长,还不是很干,但它显示了使用 promises 进行异步流控制的总体意图。

最佳答案

目的promises是保证结果...或处理失败。 Promise 可以链接起来,在函数中返回,从而进行扩展。

您不会对“覆盖” promise 感兴趣。但是,您可以做什么:

  • 处理失败案例。这是文档中的示例:
promiseB = promiseA.then(function(result) {
    // success: do something and resolve promiseB
    //          with the old or a new result
    return result;
  }, function(reason) {
    // error: handle the error if possible and
    //        resolve promiseB with newPromiseOrValue,
    //        otherwise forward the rejection to promiseB
    if (canHandle(reason)) {
     // handle the error and recover
     return newPromiseOrValue;
    }
    return $q.reject(reason);
  });
  • 在 promise 链中追加一个新的异步操作。你可以结合 promise 。如果链中调用的方法返回一个 promise ,一旦新 promise 得到解决, promise 的父级将隔离链的其余部分。

这是您可能正在寻找的模式:

angular.module('APP', ['ui.router'])
.config(['$stateProvider', function ($stateProvider) {
    $stateProvider
    .state('myState', {
        template: '<p>myState</p>',
        controller: 'myCtrl'
    });
}])
.controller('myCtrl', ['$scope', '$state', '$q', '$http', 'someAsyncServiceWithCallback',
    function ($scope, $state, $q, $http, myService) {
    $scope.buttonClicked = function () {
        $state.go('myState')
        .then(function () {
            // You can return a promise...
            // From a method that returns a promise
            // return $http.get('/myURL');

            // Or from an old-school method taking a callback:
            var deferred = $q.defer();
            myService(function(data) {
                deferred.resolve(data);
            });

            return deferred.promise;
        },
        function () {
            console.log("$state.go() failed :(");
        });
    };
}]);

关于javascript - 将 promise 传递给 Angular-UI 状态 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23492349/

相关文章:

javascript - 如何将多个选择字段的值存储到数组并在选项更改时更新数组?

javascript - 如何预测 Promises 的异步性质

javascript - 使用 Promise.mapSeries 等待回调

javascript - 从嵌套解析函数绑定(bind)到作用域

forms - 实现指令以从验证中排除隐藏的输入元素($addControl 问题)

javascript - 在 Angular 中刷新指令

javascript - 如何让response.success()等待?

javascript - 如何开始编写像 mohiomap 这样的东西?

javascript - 如何通过我的应用程序代码(即 NodeJS)将 cronjob 条目动态添加到基于 ubuntu 的容器中?

javascript - 如何从 'HTML form' 接收值到 JavaScript 代码?