javascript承诺中的可选catch

时间:2018-02-19 00:34:57

标签: javascript typescript promise es6-promise

以下内容有效:

new Promise<void>((resolve, reject) => {
      reject()
    })
    .then(() => {})
    .catch(() => {})

但我可能并不总是关心这个错误。有没有办法让捕获可选?

我尝试了这个,但它没有工作:

new Promise<void>((resolve, reject?) => {
      if (reject) reject()
    })
    .then(() => {})

Error: Uncaught (in promise): undefined

4 个答案:

答案 0 :(得分:1)

你可以解决错误何时你不关心的事情。如果您的catch返回除被拒绝的承诺之外的任何内容,则该错误不会在链中传播。

&#13;
&#13;
const ignorableError = new Error("I don't care about this error");

const myPromise = new Promise((resolve, reject) => {
      reject(ignorableError);
    })
    .then(() => {})
    .catch(error => {
      if(error == ignorableError) {
        console.log("Error ignored");
        return;
      }

      // Do something else...

    });
    
myPromise.then(() => console.log("Success"))
&#13;
&#13;
&#13;

答案 1 :(得分:1)

  

有没有办法让捕捉可选?

没有。如果您使用的承诺可能有误,则需要处理(或将其传播给您的调用者)。

当然,如果您自己创建承诺,拒绝它是可选的,您可以选择永不拒绝您的承诺,这样您就不需要处理任何错误。但是如果您使用的承诺中存在错误,并且您想忽略它们,则必须明确地这样做。只需写下

somePromise.catch(e => void e);
// or             () => { /* ignore */ }
// or             function ignore() {}

答案 2 :(得分:0)

我试图解决相同的问题,最后提出了以下实用程序:

/**
 * wraps a given promise in a new promise with a default onRejected function,
 * that handles the promise rejection if not other onRejected handler is provided.
 *
 * @param customPromise promise to wrap
 * @param defaultOnRejected default onRejected function
 */
export function promiseWithDefaultOnRejected(customPromise: Promise<any>, defaultOnRejected: (_: any) => any): Promise<any> {

  let hasCatch = false;

  function chain(promise: Promise<any>) {
    const newPromise: Promise<any> = new Promise((res, rej) => {
      return promise.then(
        res,
        function(value) {
          if (hasCatch) {
            rej(value);
          } else {
            defaultOnRejected(value);
          }
        },
      );
    });

    const originalThen = newPromise.then;

    newPromise.then = function(onfulfilled?: any, onrejected?: any) {
      const result: Promise<any> = originalThen.call(newPromise, onfulfilled, onrejected);
      if (typeof onrejected === 'function') {
        hasCatch = true;
        return result;
      } else {
        return chain(result);
      }
    };

    return newPromise;
  }

  return chain(customPromise);
}

此实用程序使您可以使用defaultOnRejected函数包装诺言,如果没有提供其他处理程序,该函数将处理被拒绝的诺言。例如:

const dontCare = promiseWithDefaultOnRejected(Promise.reject("ignored"), () => {});

那个承诺永远不会抛出“未处理的承诺拒绝”,您可以按以下方式使用它:

dontCare.then(x=>console.log("never happens")).catch(x=>console.log("happens"));

dontCare.then(x=>console.log("never happens"), x=>console.log("happens"));

或根本没有onRejected处理程序:

dontCare.then(x=>console.log("never happens")).then(x=>console.log("also never happens"));

此实用程序的一个问题是,它在使用async / await语法时无法正常工作:您仍然需要按以下方式处理“捕获”路径:

async () => {
  try {
    await promiseWithDefaultOnRejected(Promise.reject("ignored"), () => {});
  } catch (e) {
    console.log("happens");
  }
}

答案 3 :(得分:-1)

让我试着描述你的情况:

您有一个获取用户信息的服务和一个使用该服务的名为getUser的函数。当服务因任何原因失败时,getUser没有可用的用户。 getUser的结果在代码中使用了很多次,具有以下情况:

  1. 用户可以运行一个功能(代码块)。
  2. 用户无法运行功能(代码块)。
  3. 运行包含服务错误/拒绝的函数。
  4. 使用getUser结果时,您可能希望运行所有3个函数,其中包含2个函数或仅包含1个函数。

    当前getUser返回Promise,此类型似乎不适合您的情况。主要是因为拒绝承诺并且没有捕获它将导致未经处理的承诺拒绝。并且因为如果你想在用户可用的情况下运行代码,它会使函数复杂化(他们都必须检查结果而不是假设用户是否可用)。

    也许您可以尝试以下代码,请小心在not available块中进行假设,这可能是由于任何错误造成的。例如:它并不意味着用户不存在,因为它可能是网络错误。

    在示例中使用了getUser,但可以是任何返回承诺的函数,在拒绝时假定not available

    &#13;
    &#13;
    const isAvailable = promise => {
      //do not expose NOT_AVAILABLE outside this function
      const NOT_AVAILABLE = {type:"not available"};
      //no uncaught promise rejection errors by VM
      const savePromise = promise.catch(x=>x);
      return {
        available:fn=>
          promise
          .catch(e=>Promise.reject(NOT_AVAILABLE))
          .then(fn)
          .catch(
            e=>
              (e===NOT_AVAILABLE)
                ? undefined//ignore
                : Promise.reject(e)//re throw, error is not from service
          ),
        //call not available with the promise if promise rejects
        notAvailable:fn=>promise.catch(()=>fn(promise)),
        catchError:promise.catch.bind(promise)
      };
    }
    
    const service = arg =>
      (arg===1)
        ? Promise.resolve(arg)
        : Promise.reject(arg)
    
    const getUser = arg => isAvailable(service(arg));
    
    var user = getUser(2);
    //if service failed available will be skipped
    user.available(
      user=>console.log("skipped:",user)
    );
    //both catch and notAvailable will be called
    user.notAvailable(
      arg=>console.log("not available:",arg)
    );
    user.notAvailable(
      arg=>console.log("still not available:",arg)
    );
    //not handling catchError does not cause uncaught promise exception
    //  but you can inspect the error
    // user.catchError(
    //   err=>console.log("error is::",err)
    // );
    
    
    var user = getUser(1);
    //you can call available on user multiple times
    user.available(
      user=>console.log("got user:",user)
    );
    user.available(
      user=>Promise.resolve(user)
      .then(user=>console.log("still got user:",user))
      .then(x=>Promise.reject("have to catch this one though"))
      .catch(e=>console.log("ok, got error trying to run available block:",e))
    );
    
    //showing you can inspect the error
    var user = getUser(5);
    user.catchError(err=>console.log("error from service:",err));
    &#13;
    &#13;
    &#13;