Javascript 使用async/await和try/catch进行分层api调用
朋友们 我需要调用一个api;如果失败,我需要用不同的参数调用同一个api;如果它再次失败,我需要用第三个不同的参数调用同一个api;如果在那之后它最终失败了,这是一个实际的错误,并且可能会出错 我能想到的唯一方法是使用嵌套的try/catch语句,ala:Javascript 使用async/await和try/catch进行分层api调用,javascript,async-await,try-catch,es6-promise,Javascript,Async Await,Try Catch,Es6 Promise,朋友们 我需要调用一个api;如果失败,我需要用不同的参数调用同一个api;如果它再次失败,我需要用第三个不同的参数调用同一个api;如果在那之后它最终失败了,这是一个实际的错误,并且可能会出错 我能想到的唯一方法是使用嵌套的try/catch语句,ala: const identityCheck = async (slug) => { let res; try { res = await Bundle.sdk.find(slug); } catch (err) {
const identityCheck = async (slug) => {
let res;
try {
res = await Bundle.sdk.find(slug);
} catch (err) {
console.log('Fragment didn\'t work ========', slug, err);
try {
res = await Bundle.sdk.find(`package/${slug}`);
} catch (e) {
console.log('Fragment didn\'t work package ========', e);
try {
res = await Bundle.sdk.find(`${slug}-list`);
} catch (error) {
console.log('None of the fragments worked================.', error);
}
}
}
return logResponse(res);
};
identityCheck('fashion');
但似乎必须有另一种更简单的方法来做到这一点。我试着简化成一个重试函数,但结果是代码更多,更不清晰:
const identityCheck = (slug) => {
const toTry = [
slug,
`package/${slug}`,
`${slug}-list`
];
return new Promise((resolve, reject) => {
let res;
let tryValIndex = 0;
const attempt = async () => {
try {
res = await Bundle.sdk.find(toTry[tryValIndex]);
return resolve(logResponse(res));
} catch (err) {
console.log(`toTry ${toTry[tryValIndex]} did not work ========`, slug, err);
if (tryValIndex >= toTry.length) {
return reject(new Error('Everything is broken forever.'));
}
tryValIndex++;
attempt();
}
};
attempt();
});
};
感谢您的指导和意见 避免,并使用参数而不是外部范围变量作为递归计数:
function identityCheck(slug) {
const toTry = [
slug,
`package/${slug}`,
`${slug}-list`
];
async function attempt(tryIndex) {
try {
return await Bundle.sdk.find(toTry[tryIndex]);
} catch (err) {
console.log(`toTry ${toTry[tryIndex]} did not work ========`, slug, err);
if (tryIndex >= toTry.length) {
throw new Error('Everything is broken forever.'));
} else {
return attempt(tryIndex+1);
}
}
}
return attempt(0);
}
遵循Bergi的答案,但试图保留原始结构以避免“更多代码”: 这充分利用了默认参数的强大功能
同样复杂,但美学上更接近嵌套的try块,可能是一种更简单的模式。哦,注意!这是否意味着您认为此版本比嵌套的try/catch或只是一般有用的intel更好?是的,它可以更好:使用更多的
toTry
值(只需将它们添加到数组中)进行扩展更容易,如果代码中的其他位置需要类似的重试逻辑,则进一步抽象可能会有用。如果这两个原因都不重要,那就归结为简单与抽象的偏好。很好,谢谢你的快速反馈!可能会等待更多的玩笑,然后接受回答。:)是否应该在catch()
中使用console.error()
而不是console.log()
?@guest271314否,为什么?
const idCheck = async (slug, alsoTry = [`package/${slug}`, `${slug}-list`]) => {
let res;
try {
res = await Bundle.sdk.find(slug);
} catch (err) {
if (!alsoTry.length) throw err;
return idCheck(alsoTry.shift(), alsoTry);
}
return logResponse(res);
};
idCheck('fashion');