【问题标题】:Await Angular JS in a service (REST -> $resource)在服务中等待 Angular JS (REST -> $resource)
【发布时间】:2016-04-29 08:17:13
【问题描述】:

互联网上有很多关于这个话题的话题。但我还是被困住了。 由于所有信息,我再也看不到森林里的三人组了(荷兰语)

希望通过这种方式得到一些帮助。如果这是重复的,我真的很抱歉! 我主要是 C# 开发人员,但想学习一些 Web 框架。我开始@AngularJS。这是我的第一个更大的项目。所以对于 AngularJS,我还是个新手

我正在制作一种 DAL(是的 C#)。我为此使用了一项服务。我的目的当然是封装我的控制器的其余调用!

angular.module("adminApp").service("adminRestDAL", function ($resource, $q) {
var userData;

this.getUsers = function () {
    if (!userData)
        userData = $resource("/admin/users").query();
    return userData;
};

所以这是我获取所有用户的功能。我使用了“缓存”,我不会重新加载所有用户。在我的应用程序中不需要它。结果,它变得更加流畅! (减少等待)

现在我的问题是我想加载我所有的答案。我在他们的用户 ID 的帮助下将用户名添加到我的答案中。我想使用我的本地列表(缓存的)...

this.getAnswers = function () {
    //Always update answers!
    //No need for manuel caching (no global variable)

    //Make sure we have our users loaded!
    //This is exactly why I <3 C#
    //I could reuse my existing function (getUsers) and just put 'await' before it...
    this.getUsers();

    var answersData = $resource("/admin/answers").query(function (data) {
        data.forEach(function (answer) {
            answer.name = userData.find(function (u) {
                return u._id === answer.userid;
            }).name;
        });
    });
    return answersData;
};

检查 cmets。我必须等到加载用户才能继续。在 80% 的情况下,此功能有效。用户在回答之前完成,然后就没有问题了。但是如果不是,userData 是未定义的,我的答案将没有用户名......

我尝试了很多。这是我的最终解决方案(不起作用)。我做了一个单独的函数来返回查询的承诺

function getUsersAsync() {
    if (!userData)
        return $resource("/admin/users").query().$promise
            .then(
                function (success) {
                    userData = success;
                })

};

this.getAnswers = function () {
    //Always update answers!
    //No need for manuel caching (no global variable)

    //Make sure we have our users loaded!
    //This is exactly why I <3 C#
    //I could reuse my existing function (getUsers) and just put 'await' before it...
    //this.getUsers();

    getUsersAsync().then(
        function()
        {
            var answersData = $resource("/admin/answers").query(function (data) {
                data.forEach(function (answer) {
                    answer.name = userData.find(function (u) {
                        return u._id === answer.userid;
                    }).name;
                });
            });
            return answersData;
        }
    )
};

这里的“代码”等到我的用户加载完毕。但是我不能再返回我的数据(答案)了!现在返回的是我的 getAnswers() 函数之外的另一个函数...

所以我不知道如何在 AngularJS 中解决这个问题。我搜索了很多,发现了一些有用的博客。但还是卡住了。我还发现 ES7 带有 Await 和 Async 关键字...

如果您有解决此问题或使其变得更好的提示。你真的会帮助我的!

如果我的“架构”有问题,也请告诉我,就像我第一次在 AngularJS 中所说的那样。我想学习:)

此致,ErazerBrecht

【问题讨论】:

    标签: javascript angularjs async-await promise angular-resource


    【解决方案1】:

    使用原始的$promise

    this.getAnswers = function () {
    
        var answersData = $resource("/admin/answers").query();
    
        //save promise for chaining
        var secondPromise = answersData.$promise.then( function (data) {
            data.forEach(function (answer) {
                answer.name = userData.find(function (u) {
                    return u._id === answer.userid;
                }).name;
            });
        });
        //return secondPromise for chaining    
        answersData.$promise2 = secondPromise;
        return answersData;
    };
    

    在您的客户端代码中,链接第二个承诺。

    var refinedAnswers = getAnswers();
    
    refinedAnswers.$promise2.then (function onFulfilled() {
        console.log(refinedAnswers);
    };
    

    有关链接的更多信息,请参阅AngularJS $q Service API Reference -- chaining

    【讨论】:

    • 现在没有。我读了它,我的项目中有一些地方可以使用它!谢谢大佬!
    【解决方案2】:

    您不应该尝试在服务中组合您的用户和答案数据。服务只是抓取数据的封装——它是控制器,它应该组合数据,以便以有效的格式提供给您的视图。

    考虑到这一点,您的服务应该很简单:

    this.getUsers = function(){
        return $resource("/admin/users").query();
    };
    
    this.getAnswers = function(){
        return $resource("/admin/answers").query();
    };
    

    然后,在您的控制器中,您可以将缓存逻辑拼凑在一起。

    $scope.users = null;
    
    $scope.getUsers = function(){
        if($scope.users === null){
            myService.getUsers().$promise.then(function(data){
                $scope.users = data;
            });
        }
    });
    
    $scope.getAnswers = function(){
        myService.getAnswers().$promise.then(function(data){
            $scope.answers = data;
            for(var i = 0; i < $scope.answers.length; i++){
                $scope.answers[i].name = $scope.users.find(function(u){
                        return u._id === $scope.answers[i].userid;
                }).name;
            }
        });
    });
    

    【讨论】:

    • 原来我有这样的东西!但我必须在多个控制器上添加用户名。而且我不喜欢重复的代码。有没有理由我不应该在服务中这样做。顺便说一句,谢谢你的回答!
    • @ErazerBrecht 在这种情况下,您应该将getUsersgetAnswers 的缓存逻辑分离到它自己的控制器中。请记住,您可以在一个页面上拥有多个控制器。这样,只要你需要这两个功能,你就可以带上他们的控制器。按照这个范式,你可以很好地分离你的控制器/模型。
    【解决方案3】:

    当我向 Stackoverflow 发布内容时,我总是在几分钟后自己找到答案。我应该暂停一下。

    我忘记尝试在我的 getAnwsers 资源的回调中执行我的 getUser 功能。这确实解决了我的问题。

    仍然感谢回答的两个人!你就是为什么 stackoverflow 是学习新东西的好地方的原因:)

    //Private function
    //Had to do this because if need to access this function inside a callback
    //this doesn't point to this service anymore but to the callback...
    function getUsersAsync() {
        if (!userData)
            userData = $resource("/admin/users").query();
        return userData;
    };
    
    this.getUsers = function () {
        return getUsersAsync();
    };
    
    this.getAnswers = function () {
        //Always update answers!
        //No need for manuel caching (no global variable)
    
        var answersData = $resource("/admin/answers").query(function (data) {
            //Make sure we have our users loaded!
            getUsersAsync().$promise
                .then(
                    function () {
                        data.forEach(function (answer) {
                            answer.name = userData.find(function (u) {
                                return u._id === answer.userid;
                            }).name;
                        });
                    }
                )
        });
        return answersData;
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多