jquery推迟回归太早了

时间:2018-05-01 10:27:48

标签: javascript jquery promise jquery-deferred

我有以下代码:

$.when(multipleQueries(stateQueries, rowData))
    .then(function (data) {
        //do stuff with data - removed for brevity

multipleQueries函数如下:

function multipleQueries(queriesToExecute, rowData) {
    var allQueriesMapped = $.Deferred();

    // If a single query has been provided, convert it into an array
    if (Array.isArray(queriesToExecute) === false) {
        queriesToExecute = [].concat(queriesToExecute);
    }

    // Create a function for each region to run the query.
    $.when.apply($, $.map(queriesToExecute, function (query) {

        // Execute the query in the region
        return $.when(executeQuery(query.InstanceInfo, query.Query)).then(function (data) {
            var isDataMapped = $.Deferred();
            var mappedData = [];
            // Perform some data transformation
            $.when.apply($, $.map(data.results, function (value) {
                var properties = value.succinctProperties;
                 //code removed for brevity
                return $.when(mapData(properties)).then(function (mappedRow) {
                    if (mappedRow) {
                        mappedData.push(mappedRow);
                    }
                });
            })).then(function () {
                isDataMapped.resolve({
                    results: mappedData,
                    numItems: mappedData.length
                });
            });
            return isDataMapped.promise();
        }).then(function (data) {
            debugger;
            allQueriesMapped.resolve(data);
        });
    }));

    return allQueriesMapped.promise();
}

我遇到的问题是我传递了5个查询以执行到multipleQueries函数,但是在运行第一个查询后它正在调试调试器行 - 然后解析allQueriesMapped延迟然后它返回到do数据调用的东西,因为我没有收到我传入的5个queires中的所有数据,我没有看到预期的行为 - 是否有什么东西缺少我如何设置这些承诺?

注意 - 我尝试将调试器之前的.then更改为.done但是获得相同的行为,并尝试将调用代码更改为.done,如下所示,但同样也是如此。

$.when(multipleQueries(stateQueries, rowData))
    .done(function (data) {
        //do stuff with data - removed for brevity

**更新 - 执行查询功能在

之下
function executeQuery(instanceInfo, query) {
    return $.ajax({
        url: instanceInfo.Url,
        type: 'GET',
        data: {
            q: query,
            succinct: true
        },
        processData: true
    });
}

1 个答案:

答案 0 :(得分:0)

正如liben-m和charlietfl指出的那样,then位于错误的位置(请参阅***评论):

function multipleQueries(queriesToExecute, rowData) {
    var allQueriesMapped = $.Deferred();

    // If a single query has been provided, convert it into an array
    if (Array.isArray(queriesToExecute) === false) {
        queriesToExecute = [].concat(queriesToExecute);
    }

    // Create a function for each region to run the query.
    $.when.apply($, $.map(queriesToExecute, function(query) {

        // Execute the query in the region
        return $.when(executeQuery(query.InstanceInfo, query.Query)).then(function(data) {
            var isDataMapped = $.Deferred();
            var mappedData = [];
            // Perform some data transformation
            $.when.apply($, $.map(data.results, function(value) {
                var properties = value.succinctProperties;
                //code removed for brevity
                return $.when(mapData(properties)).then(function(mappedRow) {
                    if (mappedRow) {
                        mappedData.push(mappedRow);
                    }
                });
            })).then(function() {
                isDataMapped.resolve({
                    results: mappedData,
                    numItems: mappedData.length
                });
            });
            return isDataMapped.promise();
        }).then(function(data) {                    // ***
            debugger;                               // ***
            allQueriesMapped.resolve(data);         // ***
        });
    }));

    return allQueriesMapped.promise();
}

它在map内,当它应该在它之外时:

function multipleQueries(queriesToExecute, rowData) {
    var allQueriesMapped = $.Deferred();

    // If a single query has been provided, convert it into an array
    if (Array.isArray(queriesToExecute) === false) {
        queriesToExecute = [].concat(queriesToExecute);
    }

    // Create a function for each region to run the query.
    $.when.apply($, $.map(queriesToExecute, function(query) {

        // Execute the query in the region
        return $.when(executeQuery(query.InstanceInfo, query.Query)).then(function(data) {
            var isDataMapped = $.Deferred();
            var mappedData = [];
            // Perform some data transformation
            $.when.apply($, $.map(data.results, function(value) {
                var properties = value.succinctProperties;
                //code removed for brevity
                return $.when(mapData(properties)).then(function(mappedRow) {
                    if (mappedRow) {
                        mappedData.push(mappedRow);
                    }
                });
            })).then(function() {
                isDataMapped.resolve({
                    results: mappedData,
                    numItems: mappedData.length
                });
            });
            return isDataMapped.promise();
        });
    })).then(function(data) {
        debugger;
        allQueriesMapped.resolve(data);
    });

    return allQueriesMapped.promise();
}

但是那里有{strong>很多不必要地使用$.whennew $.Deferred(请参阅*** 1条评论),您可以包装参数在数组中更简单(参见*** 2注释:

function multipleQueries(queriesToExecute, rowData) {
    // If a single query has been provided, convert it into an array
    if (Array.isArray(queriesToExecute) === false) {
        queriesToExecute = [queriesToExecute]; // *** 2
    }

    // Create a function for each region to run the query.
    return $.when.apply($, $.map(queriesToExecute, function(query) { // *** 1

        // Execute the query in the region
        return executeQuery(query.InstanceInfo, query.Query).then(function(data) { // *** 1
            var mappedData = [];
            // Perform some data transformation
            return $.when.apply($, $.map(data.results, function(value) {
                var properties = value.succinctProperties;
                //code removed for brevity
                return mapData(properties).then(function(mappedRow) { // *** 1
                    if (mappedRow) {
                        mappedData.push(mappedRow);
                    }
                });
            })).then(function() {
                return {
                    results: mappedData,
                    numItems: mappedData.length
                };
            });
        });
    }));
}

如果您已经有了承诺,则无需通过new创建新承诺;只需使用then返回的那个。此外,当您已经有承诺时,从来没有必要使用$.when(thePromise)

您也可以从早期转换为内置的promise语义而不是jQuery' s Deferred中受益:

function multipleQueries(queriesToExecute, rowData) {
    // If a single query has been provided, convert it into an array
    if (Array.isArray(queriesToExecute) === false) {
        queriesToExecute = [queriesToExecute];
    }

    // Create a function for each region to run the query.
    return Promise.all(queriesToExecute.map(function(query) {
        // Execute the query in the region
        return executeQuery(query.InstanceInfo, query.Query).then(function(data) {
            return Promise.all(data.results.map(function(value) {
                var properties = value.succinctProperties;
                //code removed for brevity
                return mapData(properties);
            }).then(function(mappedData) {
                mappedData = mappedData.filter(Boolean); // Remove the falsy ones from `mapData`
                return {
                    results: mappedData,
                    numItems: mappedData.length
                };
            });
        });
    }));
}

Promise.all对于处理promises数组非常有用。但是请确保您使用的是最新的jQuery,早期版本的Deferred并没有与真正的承诺进行适当的互操作。

,我不知道(并且不能立即找到)。