jQuery 使用 ajax 调用延迟了一个循环

jQuery Deferred a loop with ajax call

我目前有一个应用程序依赖于所有正在检索的数据然后继续进一步的代码。

有一个包含循环的主函数“_update()”,这个循环调用_getData()。当收到所有数据时,我需要“_update()”将变量设置为 true。

这是我的资料:

DataCollection.prototype._update = function () {
    var _self = this;
    var _itemsResponded = 0;
    var itemData = [];

    if (_self._ready) {
        _self._ready = false;

        this.collection.forEach(function (item, index) {
            _self.apiData.id = item.id;

            var ajaxPromise = _self._getData();
            ajaxPromise.done(function(data){
                itemData[index] = data;
                _self._itemsResponded++;
            });
        })

        if (_self._itemsResponded === _self.collection.length) {
            _self._ready = true;
            console.log(itemData);
            console.log('done');
        }
    }
}

DataCollection.prototype._getData = function () {
    var _self = this;

    var ajaxPromise = $.ajax({
        url: 'ajax.php',
        data : _self.apiData,
        dataType: 'json'
    });

    var dff = $.Deferred();
    ajaxPromise.then(function(data) {
        dff.resolve(data);
    }, function(){
        dff.reject();
    });

    return dff.promise();
}

据我了解,_getData 函数工作正常。 _update 中的 .forEach 没有按预期工作。我以为 .forEach 是同步的?

由于 forEach() 方法的内容是异步的,foreach 循环将在所有 ajax 请求完成之前完成执行,因此您的检查应该像

DataCollection.prototype._update = function () {
    var _self = this;
    var _itemsResponded = 0;
    var itemData = [];

    if (_self._ready) {
        _self._ready = false;

        this.collection.forEach(function (item, index) {
            _self.apiData.id = item.id;

            var ajaxPromise = _self._getData();
            ajaxPromise.done(function (data) {
                itemData[index] = data;
                _self._itemsResponded++;

                if (_self._itemsResponded === _self.collection.length) {
                    _self._ready = true;
                    console.log(itemData);
                    console.log('done');
                }
            });
        })
    }
}

您可以使用 $.when() 将其简化为

DataCollection.prototype._update = function () {
    var _self = this;
    var _itemsResponded = 0;
    var itemData = [];

    if (_self._ready) {
        _self._ready = false;

        var promises = $.map(this.collection, function (item, index) {
            _self.apiData.id = item.id;
            return _self._getData();
        });

        $.when.apply($, promises).done(function () {
            var itemData = $.map(arguments, function (arr, idx) {
                return arr[0];
            })
            _self._ready = true;
            console.log(itemData);
            console.log('done');
        })
    }
}

DataCollection.prototype._getData = function () {
    var _self = this;

    var ajaxPromise = $.ajax({
        url: 'ajax.php',
        data: _self.apiData,
        dataType: 'json'
    });
    return ajaxPromise;
}