2014-02-19 219 views
6

我正在编写一个JavaScript函数,它发出一个HTTP请求并返回结果的承诺(但这个问题同样适用于基于回调的实现)。异步API应该同步抛出吗?

如果我马上就知道了函数提供的参数是无效的,应在功能throw同步,还是应该返回一个拒绝承诺(或者,如果你愿意,调用回调函数与Error实例)?

异步函数应该如何重要总是行为异步的方式,特别是对于错误条件?如果知道程序处于异步操作继续进行的适当状态,throw可以吗?

e.g:

function getUserById(userId, cb) { 
    if (userId !== parseInt(userId)) { 
    throw new Error('userId is not valid') 
    } 

    // make async call 
} 

// OR... 

function getUserById(userId, cb) { 
    if (userId !== parseInt(userId)) { 
    return cb(new Error('userId is not valid')) 
    } 

    // make async call 
} 
+0

也看看[为什么用于JS拒绝承诺例外? ](http://stackoverflow.com/q/21616432/1048572) – Bergi

回答

6

最终决定同步投入或不取决于你,你很可能会发现谁认为任何一方的人。重要的是记录行为并保持行为的一致性。

我的意见关于此事,您的第二个选择 - 将错误传递给回调 - 看起来更优雅。否则,最终的代码将如下所示:

try { 
    getUserById(7, function (response) { 
     if (response.isSuccess) { 
      //Success case 
     } else { 
      //Failure case 
     } 
    }); 
} catch (error) { 
    //Other failure case 
} 

这里的控制流程有点混乱。

似乎在回调中有一个单独的if/else if/else结构并放弃周围的try/catch会更好。

2

异步函数应该总是以异步方式运行,特别是对于错误条件有多重要?

Veryimportant

如果知道程序不处于异步操作进行的适当状态,throw是可以的吗?

是的,我个人认为这是可以的,当这是一个非常不同的错误从任何异步生产的,并需要分开处理。

如果已知某些用户标识无效,因为它们不是数字,并且有些用户标识将在服务器上被拒绝(例如,因为它们已被占用),您应该始终对这两种情况进行(异步)回调。如果异步错误只会出现在网络问题等方面,您可能会以不同的方式发出信号。

当“意外的”出现错误时,您总是可能会出现throw错误。如果你要求有效的用户名,你可能会抛出无效的用户名。如果你想预测无效的并期望调用者处理它们,你应该使用“统一的”错误路由,这将是异步函数的回调/拒绝承诺。

并重复@蒂莫西:您应该始终记录行为并保持行为的一致性。

1

回调API理想情况下不应该抛出,但他们抛出,因为它很难避免,因为你必须从字面上到处尝试。请记住,由throw显式抛出的错误对于抛出的函数不是必需的。另外还有一点是,用户回调可以很容易地抛出,例如在没有尝试捕获的情况下调用JSON.parse

所以这是代码将是什么样子,根据这些理想的行为:

readFile("file.json", function(err, val) { 
    if (err) { 
     console.error("unable to read file"); 
    } 
    else { 
     try { 
      val = JSON.parse(val); 
      console.log(val.success); 
     } 
     catch(e) { 
      console.error("invalid json in file"); 
     } 
    } 
}); 

不必使用2个不同的错误处理机制实在太不方便了,所以如果你不想让你的程序是卡脆弱的房子(由不写过任何尝试捕捉),你应该使用哪一个统一在一个单一的机制,所有异常处理的承诺:

readFile("file.json").then(JSON.parse).then(function(val) { 
    console.log(val.success); 
}) 
.catch(SyntaxError, function(e) { 
    console.error("invalid json in file"); 
}) 
.catch(function(e){ 
    console.error("unable to read file") 
}) 
+0

如果这个readFile抛出一个异常,它将不会被在那里定义的catch函数捕获。但是,如果readfile返回一个承诺,那么它就可以工作 –