完成循环的ajax调用数组而不是从一个调用中打破错误

时间:2016-04-12 22:39:37

标签: javascript jquery ajax callback jquery-callback

我正在尝试从数组中循环调用ajax并保存每次成功接收所有调用时打印的数据结果。

问题是如果有任何ajax调用返回错误,整个进程将中止并且不执行回调。 (尝试使用listWithErrorResult)

如何在不破坏循环的情况下推送错误内容?

JSFIDDLE

var list = ['UQ13nr6urIo', 'hxa_Z0eZ83E', 'ulHB2mNlovg'];
var listWithErrorResult = ['UQ13nr6urIo', 'hxa_Z0eZ83E', 'IWEHeIdBkc4'];

var callback = function() {
  console.log("done");
  console.log(tracks);
};

var requests = [], tracks = [];

  for(i = 0; i < list.length; i++) {
    requests.push($.ajax({
      url: 'http://www.youtubeinmp3.com/fetch/?format=JSON&video=https://www.youtube.com/watch?v='+list[i],
      dataType: "json",
      success: function(data) {
        console.log('suc');
        tracks.push(data);
      },error: function() {
	      console.log('err');
	      tracks.push('err');
	    }
    }));
  }

$.when.apply(undefined, requests).then(function(results){callback()});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

2 个答案:

答案 0 :(得分:1)

您只需将.then()句柄附加到您的ajax调用,并确保每个ajax调用都可以解析而不是拒绝。这将为您提供一系列结果,保证包含您的所有ajax调用。:

var callback = function(/* tracks are passed here as arguments */) {
  console.log("done");
  var tracks = Array.prototype.slice.call(arguments);
  console.log(tracks);
};

var requests = [];

  for(var i = 0; i < list.length; i++) {
    requests.push($.ajax({
      url: 'http://www.youtubeinmp3.com/fetch/?format=JSON&video=https://www.youtube.com/watch?v='+list[i],
      dataType: "json",
    }).then(function(data) {
        return data;
    }, function(err) {
        // convert failure into success so $.when() doesn't stop
        return $.Deferred().resolve('err');
    }));
  }

$.when.apply($, requests).then(callback);

您还可以使用我编写的$.settle()版本,让所有承诺完成并为您提供所有结果,即使某些承诺拒绝。

而不是$.when()(在第一个被拒绝的承诺上停止),您可以使用这个新函数$.settle(),它返回所有承诺的结果。它返回一个PromiseInspection对象数组,允许您查询每个promise的已解析值或拒绝原因。

你使用$.settle()就像$.when()一样,除了它返回PromiseInspection对象中的所有结果,它总是解析(永不拒绝)。由于jQuery的非标准方法是将多个参数传递给.then()处理程序(特定的Ajax调用),如果.settle()检测到多个参数,它会将它们复制到一个数组中,以便从成功的ajax返回PromiseInspection.value call是一个数组[data, textStatus, jqXHR]。这是jQuery非标准承诺中最糟糕的部分。据推测,这是在jQuery 3.x中修复/更改的,这应该是标准的兼容。此代码可以使用,因为它会自动检测.then()处理程序是否发送了多个参数并将它们转换为单个数组参数。

// ES6 version of settle
jQuery.settle = function(promises) {
    function PromiseInspection(fulfilled, val) {
        return {
            isFulfilled: function() {
                return fulfilled;
            }, isRejected: function() {
                return !fulfilled;
            }, isPending: function() {
                // PromiseInspection objects created here are never pending
                return false;
            }, value: function() {
                if (!fulfilled) {
                    throw new Error("Can't call .value() on a promise that is not fulfilled");
                }
                return val;
            }, reason: function() {
                if (fulfilled) {
                    throw new Error("Can't call .reason() on a promise that is fulfilled");
                }
                return val;
            }
        };
    }

    return $.when.apply($, promises.map(function(p) {
        return p.then(function(val) {
            if (arguments.length > 1) {
                val = Array.prototype.slice.call(arguments);
            }
            return new PromiseInspection(true, val);
        }, function(err) {
            if (arguments.length > 1) {
                err = Array.prototype.slice.call(arguments);
            }
            return new PromiseInspection(false, err);
        });
    }));
}

答案 1 :(得分:1)

当其中一个调用失败时,您必须将错误回调添加到$.when.apply then,因为它是一个错误条件。

$.when.apply(undefined, requests).then(
    function(results){callback()}, 
    function(results){callback()}
);

正在使用jsBin here