jQuery $ .when.apply没有按预期工作

时间:2018-02-02 15:58:51

标签: javascript jquery promise

我正在尝试使用jQuery的$ .when.apply在调用下一个函数(loadTab)之前等待未知数量的请求完成。我以为我正确使用它,但它肯定不会等待所有请求在调用loadTab()之前完成,所以我不确定是什么问题。这是我的代码:

function update(changes) {
    var deferreds = [];

    // must loop over changes and call individual requests
    for(var i = 0; i < changes.length; i++) {
        var direction = changes[i]['direction'];
        var data = changes[i]['data'];

        if(direction == 'add') {
            deferreds.push[add(data)];
        }
        else if(direction == 'edit') {
            deferreds.push[edit(data)];
        }
        else if(direction == 'delete') {
            deferreds.push[delete(data)];
        }
    }

    return $.when.apply($, deferreds); // this when is resolving too soon
}

function add(data) {
    return $.ajax({
        url: 'add',
        data: data,
        method: 'post',
        error: ajaxErrorFcn
    })
    .then(function(response) {
        handleTimeout(response);
    });
}

function edit(data) {
    return $.ajax({
        url: 'edit',
        data: data,
        method: 'post',
        error: ajaxErrorFcn
    })
    .then(function(response) {
        handleTimeout(response);
    });
}

function delete(data) {
    return $.ajax({
        url: 'delete',
        data: data,
        method: 'post',
        error: ajaxErrorFcn
    })
    .then(function(response) {
        handleTimeout(response);
    });
}

// this is the sequence of events I'm trying to sort out
showLoad('#container');
var changes = buildChangesArray();
update(changes)
.then(function(response) {
    if(handleTimeout(response)) {
        // this is executing before the requests triggered by update() are complete
        return loadTab()
        .then(function(response) {
            // do some other stuff
        });
    }
})
.then(function(response) {
    hideLoad('#container');
});

更新

原始问题已解决(我的.push()调用中有一个拼写错误,使用括号而不是括号),但现在我对此代码有了新的问题。我需要修改update()函数以首先运行删除操作,然后运行添加和编辑操作。这就是我所拥有的,但现在我看到添加和编辑操作在删除操作完成之前开始运行:

function update(changes) {
    var deferreds = [];
    var deletes = [];

    // must loop over changes and call individual requests
    for(var i = 0; i < changes.length; i++) {
        var direction = changes[i]['direction'];
        var data = changes[i]['data'];

        if(direction == 'add') {
            deferreds.push(add(data));
        }
        else if(direction == 'edit') {
            deferreds.push(edit(data));
        }
        else if(direction == 'delete') {
            deletes.push(delete(data));
        }
    }

    // we need to perform all the delete operations first, then the adds/edits
    return $.when.apply($, deletes) // this when is resolving too soon
    .then(function(response) {
        return $.when.apply($, deferreds);
    });
}

1 个答案:

答案 0 :(得分:2)

好吧,看起来我找到了自己的解决方案:)

我认为问题在于,当将add(),edit()和delete()的异步调用推送到数组中时,它们也会在此时被调用!这在第一个版本中不是问题,因为只要在调用loadTab()之前完成所有操作,添加,编辑和删除的执行顺序都无关紧要。但是,如果在调用任何添加或编辑之前需要调用所有删除操作,则会出现问题,因为删除之前在数组中找到的任何添加或编辑将在它们被推送到数组后立即开始运行而不是等待删除。

要解决此问题,我将代码更改为以下内容:

function update(changes) {
    var loop = function(deleteOnly) {
        var array = [];

        // must loop over changes and call individual requests
        for(var i = 0; i < changes.length; i++) {
            var direction = changes[i]['direction'];
            var data = changes[i]['data'];

            if(direction == 'add' && !deleteOnly) {
                array.push(add(data));
            }
            else if(direction == 'edit' && !deleteOnly) {
                array.push(edit(data));
            }
            else if(direction == 'delete' && deleteOnly) {
                array.push(delete(data));
            }
        }

        return array;
    };

    // we need to perform all the delete operations first
    return $.when.apply($, loop(true)) // true means only get the deletes
    .then(function(response) {
        return $.when.apply($, loop(false)); // false means only get the adds/edits
    });
}

因此,一旦将请求推入阵列,请求仍然开始运行,但这样我们可以将删除分开以确保它们首先完成。