javascript - jQuery - .always() 回调触发得太快

标签 javascript jquery jquery-deferred

我正在开发一个客户端 JS 应用程序,该应用程序应该读取 CSV 文件,每行进行一些 API 调用,然后将结果写回 CSV。我所关注的部分是如何编排请求并在所有完成后触发一个函数。这是我到目前为止所拥有的:

var requests = [];

// loop through rows
addresses.forEach(function (address, i) {
    // make request
    var addressRequest = $.ajax({
            dataType: 'json',
            url: 'http://api.com/addresses/' + address,
            success: function (data, textStatus, jqXhr) { APP.didGetAddressJson(data, i, jqXhr) },
            error: function (jqXhr, textStatus, errorThrown) { APP.didFailToGetAddressJson(errorThrown, i) },
        });
    requests.push(addressRequest);

    // make some more requests (handled by other success functions)
});

// leggo
$.when.apply($, requests).done(APP.didFinishGeocoding);

问题是,如果其中一行抛出 404,则不会调用 done 函数。我将其切换为always,现在它被调用,但不是在最后——如果我将每个回调的执行记录到控制台,它通常会在中间的某个位置。但是,如果我编辑 CSV,那么就不会出现错误,它会按预期在最后被调用。我在这里做的事情是否允许始终提前触发?

更新:是否只是控制台正在记录它 out of order

最佳答案

您需要防止错误沿着错误路径发送 $.when.apply($, requests) 返回的 Promise。

这可以通过以下方式实现:

  • .then() 链接到您的 $.ajax() 调用,而不是将“成功”和“错误”处理程序指定为 $.ajax( ) 选项。
  • 通过转换为成功来处理错误(因为这是 jQuery,您必须从错误处理程序返回已解决的 promise )。

此方法还允许您控制最终传送到 APP.didFinishGeocoding()

的数据

经过一些假设,代码的总体结构应如下所示:

function foo () {//assume there's an outer function wrapper 
    var errorMarker = '**error**';

    var requests = addresses.map(function (address, i) {
        return $.ajax({
            dataType: 'json',
            url: 'http://api.com/addresses/' + address
        }).then(function (data, textStatus, jqXhr) { //success handler
            return APP.didGetAddressJson(data, i, jqXhr); //whatever APP.didGetAddressJson() returns will appear as a result at the next stage.
        }, function (jqXhr, textStatus, errorThrown) { // error handler
            APP.didFailToGetAddressJson(errorThrown, i);
            return $.when(errorMarker);//errorMarker will appear as a result at the next stage - but can be filtered out.
        });
        // make some more requests (handled by other success functions)
    });

    return $.when.apply($, requests).then(function() {
        //first, convert arguments to an array and filter out the errors
        var results = Array.prototype.slice.call(arguments).filter(function(r) {
            return r !== errorMarker;
        });

        //then call APP.didFinishGeocoding() with the filtered results as individual arguments.
        return APP.didFinishGeocoding.apply(APP, results);

        //alternatively, call APP.didFinishGeocoding() with the filtered results as an array.
        //return APP.didFinishGeocoding(results);
    });
}

根据需要进行调整。

关于javascript - jQuery - .always() 回调触发得太快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30790604/

相关文章:

初学者的 PHP 编码帮助

Javascript 在延迟后打开一个窗口,然后在另一个延迟后关闭它

jquery - 在悬停不同元素时显示元素

php - 如何在 PHP 和 JS 中并发 session 之间进行通信?

jquery - 如何在单击时转换分组的 Canvas 元素?

javascript - 为什么我的页面跳动这么多?

javascript - 我怎样才能停止在我的 Angular 代码中的每个变量和函数之前键入 "$scope"?

javascript - jQuery Ajax 等待每个函数

javascript - 用另一个延迟对象解析jquery延迟对象

jQuery Deferred - 等待多个 AJAX 请求完成