1

我有一个函数,我在其中循环并执行一小组查询,这些查询使用 Breeze.js 返回数据块。代码的每一部分都有效,但只有一行(我尝试将查询结果添加到数组中)。我已经尝试了各种方法,但似乎无法弄清楚为什么它不起作用。

function doStuff(sourceArray, outputObservable, errorObservable) {
    var arr = [];

    _.each(sourceArray, function (sourceItem) {
        return breeze.EntityQuery
            .from("SomeTable")
            .using(manager).execute()
            .then(getSucceeded)
            .fail(getFailed);

        function getSucceeded(data) {
            _.each(data.results, function (item) {
                console.log(item); //This works
                arr.push(item);  //This doesn't work
            });
        }

        function getFailed(error) {
            errorObservable("Error retrieving data: " + error.message);
        }
    });

    outputObservable(arr);
}

这会将每个查询的所有结果输出到控制台,但不会将结果输出到数组。但是,如果我将第二行更改为,var arr = [ 1, 2, 3, 4, 5 ];那么这些值将反映在 outputObservable 中。

编辑:完整的解决方案如下。

function doStuff(sourceArray, outputObservable, errorObservable) {
    var promises = [];
    var arr = [];

    //Create an array of promises
    _.forEach(sourceArray, function (item) {
        promises.push(getDataFromServer(item.val1, item.val2));
    });

    //Wait for all promises to resolve, then set output
    Q.all(promises).then(function () {
        outputObservable(arr);
    });

    function getDataFromServer(filter1, filter2) {
        var p1 = breeze.Predicate.create("field1", "==", filter1);
        var p2 = breeze.Predicate.create("field2", "==", filter2);

        return breeze.EntityQuery
            .from("SomeTable")
            .where(p1.and(p2))
            .using(manager).execute()
            .then(getSucceeded)
            .fail(getFailed);

        function getSucceeded(data) {
            _.each(data.results, function (item) {
                arr.push(item);
            });
        }

        function getFailed(error) {
            errorObservable("Error retrieving processes: " + error.message);
        }
    }
}
4

1 回答 1

4

啊,异步的经典陷阱。getSucceeded异步调用,这意味着您将它作为回调传递给该回调,稍后EntityQuery将调用它。

到您_.each(sourceArray, ...)返回时,所有查询都已开始但仍在运行。这些都还没有完成,您的任何回调都不会被调用。因此,arr当您将其传递给 时,它仍然没有变化outputObservable。您应该能够在调试器中注意到这一点:在console.log前面添加一个outputObservable,您会看到它将在任何调用之前console.log(item)被调用。

您只想outputObservable所有异步查询完成后调用。我对 Breeze 或 underscore.js 不太熟悉,但是您需要将返回的 Promise 组合execute()成一个新的 Promise。当所有的 Promise都被解决时,这个新的 Promise 就会被解决,所以你应该给它附加一个then回调并调用outputObservable.

于 2013-08-29T23:37:11.570 回答