简体   繁体   English

javascript 承诺中的可选捕获

[英]Optional catch in javascript promises

The following is valid:以下内容有效:

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

But I might not always care about the error.但我可能并不总是关心错误。 Is there a way to make the catch optional?有没有办法让捕获成为可选的?

I tried this but it didn't work:我试过这个,但没有用:

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

Error: Uncaught (in promise): undefined

Is there a way to make the catch optional?有没有办法让捕获成为可选的?

No. If you are using a promise that might error, you need to handle that (or propagate it to your caller).不。如果您使用的承诺可能会出错,您需要处理它(或将其传播给您的调用者)。

Of course if you create the promise yourself, rejecting it is optional, and you can choose to never reject your promises so that you won't need to handle any errors.当然,如果您自己创建承诺,拒绝它是可选的,您可以选择从不拒绝您的承诺,这样您就不需要处理任何错误。 But if there are errors from promises that you are using, and you want to ignore them, you must do so explicitly.但是,如果您使用的 Promise 存在错误,并且您想忽略它们,则必须明确地这样做。 Just write随便写

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

You could resolve when the error is something you don't care about.当错误是您不关心的事情时,您可以解决。 If your catch returns anything other than a rejected promise, the error isn't propagated down the chain.如果您的 catch 返回的不是被拒绝的承诺,则错误不会沿链传播。

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

I was trying to solve the same issue, and finally come up with the following util:我试图解决同样的问题,最后想出了以下实用程序:

/**
 * 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);
}

This util lets you wrap your promises with a defaultOnRejected function that will handle the rejected promise if no other handler is provided.此实用程序允许您使用defaultOnRejected函数包装您的承诺,如果没有提供其他处理程序,该函数将处理被拒绝的承诺。 For example:例如:

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

that promise will never throw an "Unhandled Promise Rejection", and you can use it as follows:该承诺永远不会抛出“未处理的承诺拒绝”,您可以按如下方式使用它:

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

or

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

or simply without onRejected handler:或者干脆没有onRejected处理程序:

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

An issue with this util is that it is not working as expected with async/await syntax: you still need to handle the "catch" path as follows:此实用程序的一个问题是它在使用 async/await 语法时无法按预期工作:您仍然需要按如下方式处理“catch”路径:

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

Let me try to describe your situation:我试着描述一下你的情况:

You have a service that gets user information and a function called getUser that uses that service.您有一个获取用户信息的服务和一个使用该服务的名为getUser的函数。 When the service fails for any reason then getUser does not have a user available.当服务因任何原因失败时, getUser没有可用的用户。 The result of getUser is used quite a lot of times in your code with the following situation(s):在以下情况下, getUser的结果在您的代码中使用了很多次:

  1. User is available run a function (block of code).用户可以运行一个函数(代码块)。
  2. User is not available run a function (block of code).用户无法运行函数(代码块)。
  3. Run a function with the error/reject of the service.运行带有服务错误/拒绝的函数。

When using getUser result you may want to run all 3 functions, a combination of 2 of them or only one.使用getUser result 时,您可能希望运行所有 3 个函数、其中 2 个或仅一个的组合。

Current getUser returns a Promise and this type does not seem to be suitable for your situation.当前getUser返回一个 Promise 并且这种类型似乎不适合您的情况。 Mainly because rejecting a promise and not catching it will cause unhandled promise rejection.主要是因为拒绝一个承诺而不捕捉它会导致未处理的承诺拒绝。 And because if you want to run code if user is available or not it complicates the functions (they both have to check the result instead of assuming user is or is not available).并且因为如果您想在用户可用或不可用时运行代码,它会使功能复杂化(它们都必须检查结果,而不是假设用户可用或不可用)。

Maybe you can try the following code, please be careful making assumptions in the not available block, this could be due to any error.也许您可以尝试以下代码,请小心在not available块中进行假设,这可能是由于任何错误造成的。 For example: it does not mean the user does not exist because it could be a network error.例如:这并不意味着用户不存在,因为它可能是网络错误。

In the example getUser is used but can be any function that returns a promise where you assume not available on reject.在示例中使用了getUser ,但可以是任何返回承诺的函数,您假设在拒绝时not available

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM