Javascript 使用async/await和try/catch进行分层api调用

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) {

朋友们

我需要调用一个api;如果失败,我需要用不同的参数调用同一个api;如果它再次失败,我需要用第三个不同的参数调用同一个api;如果在那之后它最终失败了,这是一个实际的错误,并且可能会出错

我能想到的唯一方法是使用嵌套的try/catch语句,ala:

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