2014-02-27 21 views
1

我正在使用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; 

這個片段成功創建與給定提要URL的連接,並返回一個包含飼料數據的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); 
    }); 
}); 
+0

「如何強制循環($ .each,for循環或遞歸函數)等待來自AJAX調用的結果?」你不這樣做。您可以使用相對回調/方法來請求並根據此設置邏輯。你可以將一個延遲/承諾對象數組傳遞給'$ .when':'$ .when.apply($,arrayOfPromises);' –

+0

@Wolff能夠提供一個基本的例子或者一個網站嗎?恐怕我不完全理解你的相對回調/方法的含義。 – Vaune

回答

2

環路通過與$。每次,創造了在HTML中,每飼料包裝您發送Ajax請求之前,存儲到包裝的參考。完成後,使用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(); 
    }); 
}); 
+0

這實際上回答了我還沒有遇到的問題,並且對於我的即將到來的問題將非常有用顯示內容的任務。幸運的是,在我的應用程序中,結果不需要在頁面上顯示,直到選擇了有效的提要。謝謝!我將在未來的任務中引用這條評論。 – Vaune

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 
}); 

我不記得確切的數據將被傳遞完成(),檢查它。只有成功

+1

來自每個ajax請求的每組參數將作爲每個數組的數組發送到done參數列表。例如,在你的代碼中,data將是表示第一個請求的[parsedResponseText,statusCode,jqXHR]。處理這個問題的最佳方法是循環'arguments'數組 - 就像。 –

+0

@KevinB照常,謝謝!你的答案更合適,我想 –

+0

這似乎是我的問題最好的解決方案,根據我的初步測試。它連接到每個URL,返回JSON數據,驗證狀態代碼,然後確保我可以省略不良連接,並在成功提要上繼續進行內容驗證。謝謝! – Vaune

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?? 
}); 
+0

編輯使用var外部封閉,並且只在返回結束時返回的情況下,使用對象,因此它的承諾狀態 –