我有一个带有URL的数组,我必须遍历它才能下载HTML文件。如果某个URL无法加载(例如由于连接问题),则该HTML文件将不会下载,因为循环将转到下一个迭代。我的目标是,如果发生错误,程序应将当前迭代重复3次,然后转到下一个迭代。
这是我想要实现的目标:
let filteredUrls = [ 'url1', 'url2', 'url3'];
for (let id in filteredUrls) {
let currentUrl = filteredUrls[id];
try {
//open currentUrl, do some stuff...
} catch (error) {
//if there's an error, repeat the current loop 3 times,
//after that, move to the next iteration
}
}
我该怎么做?有办法吗?
答案 0 :(得分:1)
如果您的下载代码是异步的,那么您可能要使用递归函数,而不是仅仅再次重复循环。
let filteredUrls = [ 'url1', 'url2', 'url3'];
for (let id in filteredUrls) {
let currentUrl = filteredUrls[id];
downloadFile( currentUrl, 0 );
}
function downloadFile( url, tryCount ) {
try {
//open currentUrl, do some stuff...
} catch (error) {
tryCount++;
if ( tryCount < 3 ) {
downloadFile( url, tryCount );
}
}
}
答案 1 :(得分:1)
您还没有显示如何获取页面内容,但是我假设您使用的是类似fetch
或XMLHttpRequest
的东西。如果您使用的是提取,它会返回一个Promise,该承诺会因网络错误而拒绝,这意味着您可以将回调附加到其.catch()
方法上,以重试提取。如果您使用的是XMLHttpRequest,则它有一个onerror
事件,您可以附加相同的重试回调。
我建议您将内容获取代码分解为一个接受URL和重试编号的函数,然后返回XMLHttpRequest或fetch
Promise。这样,您可以使错误回调仅再次调用相同的函数,但是为重试参数传递了retries-1
。
示例:
function fetchWithRetry(url, tries) {
if (tries <= 0) { return Promise.reject('Could not fetch.'); }
return fetch(url).catch(() => fetchWithRetry(url, tries - 1));
}
// OR:
function fetchWithRetry(url, tries) {
if (tries <= 0) { throw new Error('Could not fetch.'); }
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onerror = () => fetchWithRetry(url, tries - 1);
xhr.send();
return xhr;
}
基于Promise的方法要好一些,因为由于应许链接,您的主要代码可以仅假定重试已得到处理,并且可以附加.then()
,如果任何尝试成功,它将运行。 .catch()
仅在所有尝试均失败的情况下才会运行。使用XHR,它基于事件的性质意味着,如果必须重试,则您的主代码将丢失对当前XHR的引用。