我有一个URL数组,我想执行一个fetch()
请求:
const urls = [
'https://dewnuf111111.com/configuration',
'https://dewnuf222222.com/configuration',
'https://bcsmania.co.uk/test.json'
];
如果抓取错误(例如,该网站不存在,内部错误等),我希望它尝试下一个URL,因此我添加了一个增量器。
一旦到达有效网址并成功发出请求,它就应该简单地console.log('DONE')
,但我似乎无法使其正常工作。
这是我到目前为止编写的代码:
const urls = [
'https://dewnuf111111.com/configuration',
'https://dewnuf222222.com/configuration',
'https://bcsmania.co.uk/test.json'
];
let obj = {a: 'test'};
let counter = 0;
function ajax(url) {
// Check for for last URL in the array
if (counter < urls.length) {
return fetch(url)
.then(response => {
// Combine objects
obj = Object.assign(obj, response.json());
console.log(urls[counter], obj);
return Promise.resolve(obj);
}).catch(error => {
counter++;
// Fetch next URL
ajax(urls[counter]);
});
}
}
function getConfigurations() {
return ajax(urls[counter]);
}
getConfigurations().then((configurations) => {
console.log('DONE', configurations);
});
这里是JSFiddle,用于预览。
有人能说出我可能要去哪里的地方吗?
我是否需要使函数async
,然后使await
成为结果?
答案 0 :(得分:2)
您还需要在捕获中返回Promise,以便也可以从中进行链接:
.catch(error => {
counter++;
// return Fetch next URL
return ajax(urls[counter]);
});
答案 1 :(得分:1)
在这里,您正在将异步代码与同步代码混合在一起。由于您的循环本质上是同步的,因此它不会等待结果,并且一旦代码解析就打印完成。最简单的解决方案是,您可以使用async-await输入来循环url。我在下面给出了示例。请检查。
https://jsfiddle.net/gof91e6v/
const urls = [
"https://dewnuf111111.com/configuration",
"https://dewnuf222222.com/configuration",
"https://bcsmania.co.uk/test.json"
];
let obj = { a: "test" };
async function getConfigurations(urls) {
let result = null;
if (counter < urls.length) {
for (let count = 0, len = urls.length; count < len; count++) {
try {
result = await fetch(urls[count]);
} catch (e) {}
if (result) break;
}
}
return result;
}
getConfigurations(urls).then(configurations => {
console.log("DONE", configurations);
});
答案 2 :(得分:1)
我希望将获取网址列表与处理方式分开(例如您的Object.assign
调用。)
在此版本中,fetchFirstWorking
接受URL列表并响应Promise,该Promise将通过获取第一个实时URL的结果得到解决。请注意,它使用递归而不是计数器,因此将状态管理保持在最低水平。
getConfiguration
保存业务逻辑。
const fetchFirstWorking = ( [url, ...urls], conf ) => url
? fetch (url, conf)
.catch ( _ => fetchFirstWorking (urls) )
: Promise .reject ('no urls could be loaded')
const getConfigurations = (urls) =>
fetchFirstWorking(urls)
.then ( res => res .json () )
.then ( res => Object .assign ({a: 'test'}, res) )
const urls = [
'https://dewnuf111111.com/configuration',
'https://dewnuf222222.com/configuration',
'https://bcsmania.co.uk/test.json'
]
getConfigurations (urls)
.then(console.log)
.catch(console.warn)
如果将最后一个URL替换为另一个虚拟对象,则会看到它生成控制台警告:
const fetchFirstWorking = ( [url, ...urls], conf ) => url
? fetch (url, conf)
.catch ( _ => fetchFirstWorking(urls) )
: Promise .reject ('no urls could be loaded')
const getConfigurations = (urls) =>
fetchFirstWorking(urls)
.then ( res => res .json () )
.then ( res => Object .assign ({a: 'test'}, res) )
const urls = [
'https://dewnuf111111.com/configuration',
'https://dewnuf222222.com/configuration',
'https://dewnuf333333.com/configuration',
]
getConfigurations (urls)
.then(console.log)
.catch(console.warn)