异步URL验证导致问题

时间:2014-02-27 20:34:12

标签: javascript php jquery ajax rss

我正在使用Google的Feed API构建一种RSS Feed阅读器。经过多次试验和错误,我已经能够通过PHP实例化与给定RSS URL的连接,并返回JSON对象。我遇到的问题是我试图从数组中验证多个URL,但由于AJAX的异步性质以及通过Google API加载时滞,结果代码会在验证完成之前触发。我尝试过这样的事情:强制同步,setTimeouts,.promise调用验证的对象,但是我没有在哪里。任何帮助都会受到极大的赞赏。

我的代码:
PHP

$feed = $_POST['feed'];
$url = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=&q=" . $feed;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_REFERER, www.mywebsiteurl.com);
$body = curl_exec($ch);
curl_close($ch);
echo $body;

此代码段成功创建与指定Feed网址的连接,并返回包含Feed数据的JSON对象。我用以下的AJAX调用调用这个外部php脚本:

AJAX:

var conn = $.ajax({
     url : "php/feedlog.php",
     type : "post",
     data : {feed: feed_a[i]}
});

conn.done(function (data){
    var err = eval('(' + data + ')' ).responseStatus;
    if (err==200){
        console.log("Success");
    } else if (err==400){
        console.log("Failure with: " + err);
    }
}); 

此代码可以完美地用于单个连接尝试,但我需要线性地逐步执行一系列提要,测试提要,等待连接结果,然后继续执行数组中的下一个提要,或者打破成功连接。

我试图为feed_a []使用$ .each语句,但是循环的触发速度比返回的结果要快。我想我需要操作缓冲区,但我不确定如何实现它。

与往常一样,如果需要,我可以根据要求提供额外的代码,之前的尝试或更多的澄清。如果需要,我可以在我的网站上现场托管代码以进行演示。

更直接的问题:如何强制循环($ .each,for循环或递归函数)等待AJAX​​调用的结果?

此外,为了将来更好地提出问题,有人可以解释为什么我的问题可能会被标记下来吗?

编辑:感谢大家快速回复!以下代码似乎可以解决我的问题:

$.each(v_feed, function(_,url){
    $.ajax("php/feedlog.php",{
        type: "POST",
        data: { feed: url }
    }).done(function(data){
        var err = eval('(' + data + ')' ).responseStatus;
        if (err == 200){
            console.log("success with: " + data);
        } else if (err == 400){
            console.log("fail with: " + data);
            console.log("removing from valid array");
            v_feed.splice(v_feed.length - _, 1);
        }
        //console.log(err);
    }).fail(function(){
        console.log("Fail");
    }).complete(function(){
        console.log(v_feed);
    });
});

3 个答案:

答案 0 :(得分:2)

试试:

var arrayOfPromises = [];

//inside each/for loop, push request in array
arrayOfPromises.push($.ajax({
     url : "php/feedlog.php",
     type : "post",
     data : {feed: feed_a[i]}
}));

然后在循环之外:

$.when.apply($, arrayOfPromises).done(function(data){
     //all requests are done
});

我不记得确切地将哪些数据传递给done(),检查它。

答案 1 :(得分:2)

使用$ .each循环,在发送ajax请求之前为html中的每个feed创建包装器,存储对包装器的引用。完成后,使用Feed填充包装器。这样您就可以一次性检索它们,同时仍以正确的顺序将它们添加到页面中,而无需等待它们全部完成。

$.each(feedArr, function(_,url){
    var wrapper = $("<div>").appendTo(someel);
    $.ajax("feed.php",{
        type: "POST",
        data: { url: url }
    }).done(function(data){
        // process data...
        wrapper.append(generateFeedHTML(data));
    }).fail(function(){
        wrapper.remove();
    });
});

答案 2 :(得分:1)

仅在成功时启动下一个电话:

var worked = {status:true},
 conn = function(successLogic){
 if(feed_a[i]) // I assume this is the loop end condition...
   $.ajax({
     url : "php/feedlog.php",
     type : "post",
     data : {feed: feed_a[i]},
     success: function(data){
       if(successLogic(data));
         worked.status = worked.status && conn(successLogic); // Recursion instead of iteration!
     },
     error: function(err){
       worked.status = false;
       // your error code
     }
   });
   else
     return worked;
};

var completedRecusionPromise = conn(function(data){
  var obj;
  try{
   obj = JSON.parse(data);
  }catch(e){ console.log(e); }
  return !!obj; // Assuming you just want valid JSON??
});