调用Promise时,调用函数的正确错误处理模式是什么?

时间:2019-01-22 13:33:46

标签: javascript asynchronous promise

我对Promises和async / await完全陌生,只是阅读了教程等内容,所以我希望我可能缺少一些基本知识。

我在几个地方都看到过这种代码模式,但是我想也许不应该相信它:

async function myFunc() {
  try {
      var result = await doSomethingAsync();
      console.log(result);
  } 
  catch(error) {
      console.error(error); // hmm
  }
}

myFunc();

使用上述模式考虑以下情形:

const doSomethingAsync = behaviour => new Promise((resolve, reject) => {  
    // use setTimeout to simulate e.g. an async webapi callback func
    setTimeout(() => {                             
        if(behaviour === "set resolve") 
            resolve("resolved");
        if(behaviour === "set reject") 
            reject("rejected");
        if(behaviour === "set after timeout error") 
            throw new Error("something went wrong after setTimeout returned");
    }, 500);

    if(behaviour === "set promise error")
        throw new Error("something went wrong in promise");
});

async function myFunc(behaviour) {
  try {
        // wait for promise to complete
        var result = await doSomethingAsync(behaviour);
        console.log(result);
  } 
  catch(error) {
      console.error("caught:" + error); // will catch reject and promise error, 
                                        // but NOT after setTimeout error
  }
}

myFunc("set promise error");  // caught:Error: something went wrong in promise 
myFunc("set resolve"); // resolved 
myFunc("set reject"); // caught:rejected 
myFunc("set after timeout error"); // Uncaught Error: something went
                                   // wrong after setTimeout returned
                                   // UHOH!!

因此,该模式似乎有点误导,因为它无法捕获setTimeout错误,而人们倾向于将catch()视为全部捕获。

当然,将setTimeout更改为具有内部catch将解决未捕获的错误问题:

const doSomethingAsync = behaviour => new Promise((resolve, reject) => {  
    // use setTimeout to simulate e.g. an async webapi call
    setTimeout(() => {            
        try { // ... 
        }
        catch(e) { reject("an error"); }
    }, 500);
});

所以,我的问题是:

  1. 据我所知,Promise用作回调的替代品,即用于包装诸如setTimeout之类的异步调用。那么,在Promise中是否应该始终有一个内部try / catch->拒绝模式? (以便调用者可以正常处理错误)。做例如所有节点库都以这种方式工作? 我看不到呼叫者自己可以处理的任何方式。

  2. 我发现该模式具有误导性,这样的模式会更好吗?

    async function myFunc(behaviour) {
      try {
            var result = await doSomethingAsync(behaviour);
                            .catch(e) { console.log("expected reject happened:" + e) };
      } 
      catch(error) {
          console.error("something totally unexpected happened:" + error); 
      }
    }

0 个答案:

没有答案