0

我正在寻找有关处理承诺和字符串创建的通用解决方案。基本上是时间问题。此代码不是实际代码,但说明了我的问题和我尝试的解决方案。

我有两个需要组合的 json 对象。一个或两个对象可能具有需要来自 API 的某些信息的值。此信息用于创建标签,显示已组合的两个对象。

具有已定义标签的对象(无需查找):

var object1 = {
    type: "some.type",
    distribution: 50,
    label: "Male"
}

具有动态标签的对象(以及通过服务 $http 请求获取标签的伪代码):

var object2 = {
    type: "some.type",
    distribution: 50,
    value: "68"
}

// call service to get the data to populate the label
myService.getDynamicObjectData("68").then(function(response){
    // should be "Alaska"
    object2.label = response.data.label; 
});

所需组合:

var combinedObj = {
    type: "some.type.combined",
    distribution: 25,
    // ideally label would be "Male > Alaska"
    label: object1.label + " > " + object2.label
    values: [object1, object2]
}

我的问题是 object2.label 直到创建组合对象之后才填充,特别是标签字符串。在视图中,我看到“男性 > 未定义”。我已经设法达到“男性> 68”,但这并没有真正帮助。当我不组合对象时,一旦解决了承诺,标签就会更新,并且没有问题让“阿拉斯加”和“男性”显示为两个唯一条目。当我从两个标签组合并创建字符串时,它发生得太快了。

object1 和 object2 在一个服务中创建,该服务处理读取数据并创建这些对象以供内部使用,然后此组合代码在另一个处理此类数据嵌套的服务中;所以我不能真正使用观察者来更新该值。

我已经尝试将标签设置为希望能够奏效的承诺,但它没有:

var promise = myService.getDynamicObjectData("68").then(function(response){
    // should be "Alaska"
    object2.label = response.data.label; 
});

var object2 = {
    type: "some.type",
    distribution: 50,
    value: "68",
    label: promise
}

标签只是一个对象,里面有 {then()、catch()、finally()}。即使 then() 返回正确的值,我也无法找到获取实际返回值的方法。

我尝试使用数组和过滤器,这样直到最后一段时间我才真正创建字符串,这意味着由于字符串不是“真实的”,所以它应该在模型最终更新时工作(如单独显示对象时会这样做):

var combined = {
    type: "some.type.combined",
    distribution: 25,
    label: [object1.label, object2.label]
    values: [object1, object2]
}

module.filter('labelFilter', function(){
    return function(input){
        if(angular.isArray(input)){
            // but input[1].label is a promise object, how do I get the resolved value?
            return input[0].label + " > " + input[1].label 
        }
        return input;
    }
});

所以,我转向社区,看看我能在这里做什么。如何创建一个字符串,其中部分字符串基于承诺的结果?我想如果我使用 $resource,我可以设置 label: labelResource,并且 labelResource 最终会解析为我想要的实际数据(即使是我想要的数据的父对象也会有帮助)。不幸的是,还有其他逻辑对于 $resource 来说太复杂了,所以如果不进行一些重构,我就无法使用它。我希望能够将标签设置为 $q.deferred.result 之类的东西并让它全部解决(即使我仍然需要过滤器)。

无论如何,感谢您的收看!

4

2 回答 2

1

你可以用 promises 和 $q 来做到这一点

https://docs.angularjs.org/api/ng/service/ $q 转到页面底部,您可以在其中找到 $q.all 这基本上是您问题的解决方案,当所有承诺都将得到解决时,您就可以调用你的函数来加入字符串(标签)

于 2014-06-13T20:41:00.127 回答
0

您可以尝试查看此处提到的方法以在过滤器中执行此操作。

我做了一个简单的小提琴演示异步过滤器,你可以用它作为这个问题的起点-> http://jsfiddle.net/7eqsc/5/

    angular.module('myApp', [])
    .controller('myCtrl', function ($scope, $timeout) {


})
      .filter('test', function ($q, $timeout) {
         var cache={};
       return function (input) {
        if (!cache[input]){
        //I used timeout, but anything that needs to happen async can happen here
        $timeout(function () {
            //do something with the input
            cache[input]=input+'!';
        }, 500);
            //return something in the meanwhile to hold it
            return 'loading';
        }
        else return cache[input];
    }
   });

当然没有测试,但尝试类似:

module.filter('labelFilter', function () {
var cache = {};
return function (input) {
    var cachedItem = cache[inputHash(input)];
    if (!cachedItem) {
        if (angular.isArray(input)) {
            input[0].label.then(function (text) {
                //once the promise is finished, put the correct verison inside the cache
                cache[inputHash(input)].label = text + " > " + input[1].label;
            })
            //meanwhile, return the unmodified object.
            return input;
        }
    } 
    return cachedItem;
}

//you'll have to identify each input for the cache somehow.. it can be a combination of fields for example
function inputHash(input) {
    return input.id; //some unique identifier..
}

});

请记住,将 Promise 称为“标签”可能会非常令人困惑,您应该尝试重新组织您的代码,以便在 prop 内部包含 Promise 时更清楚。

祝你好运!

于 2014-06-13T20:56:26.157 回答