一个asynchronousAPI是否应该同步抛出?

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

如果我立即知道提供给函数的参数是无效的,那么函数应该同步throw ,还是应该返回一个被拒绝的promise(或者,如果你愿意的话,用Error实例调用callback函数)?

asynchronous函数应该总是以asynchronous的方式运行,特别是对于错误条件,这有多重要? 如果知道程序不是处于asynchronous操作的适当状态,可以throw吗?

例如:

 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 } 

最终决定同步抛出取决于你,你很可能会发现有人争论任何一方。 重要的是logging行为并保持行为的一致性。

我对此事的看法是,你的第二个select – 将错误传递给callback – 看起来更优雅。 否则,你最终会看到如下代码:

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

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

似乎在callback中有一个if / else if / else结构会更好,并放弃周围的try / catch

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

非常 重要 。

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

是的,我个人认为,这与任何asynchronous生成的错误是完全不同的,并且无论如何都需要单独处理。

如果一些userids被认为是无效的,因为它们不是数字,而有些则会被服务器拒绝(例如,因为它们已经被占用),你应该始终对这两种情况进行(asynchronous)callback。 如果asynchronous错误只会出现在networking问题等等,你可能会发出不同的信号。

当出现“ 意想不到的 ”错误时,你总是会throw 。 如果你要求有效的userids,你可能会扔无效的。 如果你想预测无效的,并希望调用者处理它们,你应该使用“统一的”错误路由,这将是asynchronous函数的callback/拒绝承诺。

重复@蒂莫西:你应该总是logging行为并保持行为的一致性。

callbackAPI理想情况下不应该抛出,但他们抛出,因为它是很难避免,因为你必须从字面上尝试抓住无处不在。 请记住,通过throw显式抛出错误对于抛出的函数不是必需的。 另外还有一点是,用户callback可以很容易地抛出,例如调用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种不同的error handling机制是非常不方便的,所以如果你不想让你的程序成为一个脆弱的卡片屋(通过不写任何try catch),你应该使用promise来统一在一个机制下的所有exception处理:

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