【问题标题】:Receiving incomplete data through promise $q angularjs通过 promise $q angularjs 接收不完整的数据
【发布时间】:2015-01-19 12:02:29
【问题描述】:

当我通过控制台记录具有 3 个主要元素的对象时,我期望获得的数据存在差异:

HERE ARE THE VARIATIONS IN THE ARRAYS , then the results are:
Object {usr: Object, cat: Array[2], exp: Array[2]} // Incomplete data
Object {usr: Object, cat: Array[3], exp: Array[3]} // complete data

我正在使用 DexieJS 库从 indexedDB 获取这些数据。我有一个函数调用 3 个函数来获取所有数据,即 usr、cat、exp。我缺少 cat 和 exp 函数中的数据。我的猜测因使用不良承诺而丢失。 这是获取 cat 数据的内容(exp 与更改名称几乎相同):

regresarCat: function () {
        var deferred = $q.defer();
        var cats = [];
        var count = 0;
        db.transaction("rw", db.categories, function () {
            db.categories.orderBy('nameCat').each(function (cat) {
                cats[count] = cat;
                count++;
                deferred.resolve(cats);
            });

        }).catch (function (e) {
            deferred.reject(e);
        });
        return deferred.promise;
    }

获取所有数据函数(regresarTodo)是下一个:

regresarTodo: function(){
var deferred = $q.defer();
var todo = [];

this.regresarUsr().then(function(user){
    todo['usr'] = user;
    deferred.resolve(todo);
    return deferred.promise;
}).catch(function(e) {
    deferred.reject(e)
});

this.regresarCat().then(function(cate){
    todo['cat'] = cate;
    deferred.resolve(todo);
    return deferred.promise;
}).catch(function(e) {
    deferred.reject(e)
});

this.regresarExp().then(function(exps){
    todo['exp'] = exps;
    deferred.resolve(todo);
    return deferred.promise;
}).catch(function(e) {
    deferred.reject(e)
});

$q.all({ usr: this.regresarUsr(), cat: this.regresarCat(), exp: this.regresarExp() }).then(function(respuesta){
    console.log('Got promise');
    console.log(respuesta);
    deferred.resolve(respuesta);
});

return deferred.promise;
}

我找不到我的错误,我看到了这些变化,因为我使用间隔调用 regresarTodo 函数,我看到第一次并不总是完整,有时第二次打印完成但保持变化。我需要在第一时间获取所有数据。很迷茫,谢谢

【问题讨论】:

  • @WayneEllery 那行不通。 .each 回调被异步调用。

标签: javascript angularjs promise indexeddb angular-promise


【解决方案1】:

您在 .each() 处理程序中拥有 deferred.resolve(cats),但承诺绝不应该是 resolve()d 超过一次。

您使用的库提供了.toArray() 方法,因此您应该使用它。

您也不需要使用延迟对象从头开始创建承诺; .toArray()db.transaction() 为您创建承诺:

regresarCat: function () {
    return db.transaction("rw", db.categories, function () {
        return db.categories.orderBy('nameCat').toArray();
    });
}

请注意,这也会使您的函数缩短约 70%。


您在第二个代码示例中有类似的问题。当您根本不需要在这里使用延迟时,您正在尝试在三个不同的地方解析单个 deferred。你可以直接将你的承诺传递给$q.all()
regresarTodo: function() {
    return $q.all([this.regresarUsr(), this.regresarCat(), this.regresarExp()])
    .then(function(respuesta){
        console.log('Got values');
        console.log(respuesta);
        return { usr: respuesta[0], cat: respuesta[1], exp: respuesta[2] };
    });
}

再次注意这如何使您的代码缩短约 80%。还要注意$q.all() 的参数应该是一个数组

【讨论】:

  • 太棒了,我非常喜欢您的解决方案:D,我为您的代码更改了 regresarCat 函数,现在我可以在控制台中看到一个 t 对象,我可以在 dev chrome 中看到我如何单击并查看_value 与 Array[3],我试图获取该值并执行此操作: var categorias = function(){ var uno = MGAindexdb.regresarCat(); console.log('Dentro de categorias');控制台.log(uno); // 打印 t {_state: null, _value: null, _deferreds: Array[0], _catched: false, _PSD: null…} } 我尝试记录值,但我得到 null,点击时我看到了对象跨度>
  • @GabouhSk8 总是乐于提供帮助。 :)
【解决方案2】:

您基本上需要为每个调用使用不同的延迟对象。并且您需要在收到来自该调用的数据后解决相应的延迟。

然后随后形成一个包含所有上述延迟对象的承诺的数组,并在

中使用该数组
$q.all(allPromisesArray).then(function(){
    /* your stuff here */
})

【讨论】:

  • 这里实际上根本不需要使用延迟对象。
猜你喜欢
  • 2019-05-08
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-23
相关资源
最近更新 更多