2016-03-16 16 views
2

可以假設我有以下幾點:調用http.get順序當列表長度未知

var myurls = ['http://server1.com', 'http://server2.com', 'http:sever2.com', etc ] 

的每個網址是一個「回退」,應該只使用,如果前一個無法達成。換句話說,這個列表指定了一個優先級。讓我們也假設這個列表可以是任意長度的 - 我不知道並且必須迭代。

我該如何着手編寫一個函數,讓我們說可循環遍歷這個數組並返回第一個可到達的服務器的「可達性」?

我不能做$http.all,因爲它是平行的。我無法運行while循環,其中$http.get因爲結果可能會晚一些,同時我的UI會凍結。

請注意我沒有使用jQuery。我正在使用離子,它有一個jQuery-lite版本。

我見過的各種例子都談論了鏈接它們的.then,如果你事先知道URL的#號,這很好,但我不知道。

感謝

+0

你怎麼能有一個未知長度的數組? 'myurls.length'? – jib

回答

1

我想遞歸和鏈接可能會滿足您的需求:

var findFirstReachableUrl = function (urls) { 
    if (urls.length > 0) { 
    return $http.get(urls[0]).then(function() { 
     return urls[0]; 
    }, function() { 
     return findFirstReachableUrl(urls.slice(1)); 
    }); 
    } else { 
    return $q.reject("No reachable URL"); 
    } 
} 

電話:

findFirstReachableUrl(myurls).then(function (firstReachableUrl) { 
    // OK: do something with firstReachableUrl 
}, function() { 
    // KO: no url could be reached 
}); 
+1

非常感謝。這工作得很好。我已經開始編寫一個遞歸例程,但你的代碼更優雅。 – user1361529

+0

我正在重新看這個代碼,並想知道爲什麼我們不需要在第4行返回''q.resolve(urls [0])''而只是'''返回urls [0]'''工作? – user1361529

+1

@ user1361529因爲'then'方法返回'Promise',請參閱https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then#Chaining。 – sp00m

2

只是減少在陣列上:

myurls.reduce((p, url) => p.catch(() => http.get(url).then(() => url)), 
       Promise.reject()); 

流程說明:

它是基於使用關上降低了建造一個承諾鏈,像這樣的也許更common pattern[func1, func2].reduce((p, f) => p.then(f), Promise.resolve());相當於Promise.resolve().then(func1).then(func2)(的reduce最後arg是初始值)。

就你而言,由於你在重試失敗,你想要建立一個重試(或拒絕)鏈,所以我們必須改爲Promise.reject()Promise.reject().catch(func1).catch(func2)

+0

我從來不知道存在減少。雖然你的解決方案看起來不錯,但我必須承認,我的JS技能太基本,無法完全理解。介意告訴我這裏的流程?具體來說,我在哪裏可以讀到''()''和''=>''做什麼? – user1361529

+1

這是一個[箭頭函數](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions),只是這種情況下的簡寫。將'x => x * x'替換爲'function(x){return x * x;如果你願意。 – jib

+0

謝謝。看起來我只能接受1個答案,而不是2個。由於我正在使用sp00m的解決方案,因此我希望將其作爲我接受的選擇。我的答案讓我學到了很多新東西。 – user1361529