使用promises数组和$ .when忽略AJAX错误

时间:2014-05-12 20:06:52

标签: jquery ajax promise getjson jquery-deferred

我有以下代码从YouTube视频ID数组中获取JSON。当所有视频都存在且查询成功时,它的效果很好。它发送了几个getJSON请求,当它们全部完成时...... $。when.done()触发,我可以处理结果数据。

var
  results  = {},
  promises = [];

$(document).ready(function() {

  var
    vids = [
    'ozj2-bnTL3s',
    'EAZ4Tlt8MQ4',
    'Xn9o7cxqVoA'
    // ,'this-videoid-doesnot-exists'
  ],
  url = 'http://gdata.youtube.com/feeds/api/videos/{{vid}}?v=2&alt=json';

  $.each(vids, function(idx, vid){
    var
      u = url.replace('{{vid}}', vids[idx]),
      p = null;

    p = $.getJSON( u ).done(function(data) {
      results[vid] = data.entry;
    });

    promises.push(p);
  });

  $.when.apply($, promises).done(function(){
    console.log(results);
  });

});

但是......在最终应用中,如果所有视频仍然存在于YouTube中,我无法控制,我已经意识到有时列表中的一个(或几个)视频可能已被删除...或者我从DB获得的ID不正确。

有没有什么方法可以安全地添加到结果变量只有成功whiteout触发$ .when.fail()的视频?并等待所有查询完成...

我的意思是,我的最终目标是从存在的视频中获取数据(那些数据已成功检索到的数据),并以某种方式忽略那些不存在或不存在的视频...而我现在不知道怎么做。

任何想法/方法都会受到欢迎。 TIA!
您可以在this JSFiddle

中找到代码

2 个答案:

答案 0 :(得分:8)

不幸的是,jQuery并没有提供这种功能。

很高兴,你可以很容易地自己实现它。

var url = 'http://gdata.youtube.com/feeds/api/videos/{{vid}}?v=2&alt=json';
function getVideo(vid){
    var u = url.replace('{{vid}}', vid);
    return $.getJSON( u ).then(function(res){
         return {video:vid,result:res.entry};
    });
}
var promises = ['ozj2-bnTL3s','EAZ4Tlt8MQ4',"doesn'texist"].map(getVideo);

some(promises).then(function(results){
    for(var i = 0; i < results.length; i++) {
        console.log(results[i]); // log
    }
});



// get a hook on when all of the promises resolve, some fulfill
// this is reusable, you can use this whenever you need to hook on some promises
// fulfilling but all resolving.
function some(promises){
    var d = $.Deferred(), results = [];
    var remaining = promises.length;
    for(var i = 0; i < promises.length; i++){
        promises[i].then(function(res){
            results.push(res); // on success, add to results
        }).always(function(res){
            remaining--; // always mark as finished
            if(!remaining) d.resolve(results);
        })
    }
    return d.promise(); // return a promise on the remaining values
}

这里是working JSFiddle的结果。

答案 1 :(得分:-1)

在纯粹的javascript Promise实现(或Q或其他专用库)中,你可以这样做:

function getVideo(id) {
  return new Promise(function(resolve, reject) {
    var request = new XMLHttpRequest();
    request.open('GET', 'url = 'http://gdata.youtube.com/feeds/api/videos/' + id + '?v=2&alt=json');
    request.onload = function() {
      if (request.status == 200) {
        resolve(request.response); //we get the data here. So, resolve the Promise
      } else {
        reject(Error(request.statusText)); //if status is not 200 OK, reject.
      }
    };

    request.onerror = function() {
      reject(Error("Error fetching data.")); //error occurred, reject the Promise
    };

    request.send(); //send the request
  });
}

function fetchVideos() {
  var vids = [
    'ozj2-bnTL3s',
    'EAZ4Tlt8MQ4',
    'Xn9o7cxqVoA'
    // ,'this-videoid-doesnot-exists'
  ]
  var promises = [];
  for (var i in vids) {
    promises.push(getVideo(vids[i]));
  }
  Promise.all(promises).then(function(dataArr) {
    dataArr.forEach(function(data) {
      console.log(data.entry);
    });
  }).catch(function(err){
      console.log(err);
  });
}