JavaScript Promise: Reject handler vs catch
我遇到过多个应用程序,其中使用catch优先于rejectHandler。
例如:
宁愿
1 | new Promise.then(resolveHandler).catch() |
代替
1 | new Promise().then(resolveHandler, rejectHandler).catch() |
这有什么特别的原因??
我发现
1 | new Promise().then(resolveHandler, rejectHandler).catch() |
更有用因为
有人知道为什么rejectHandler使用不多的特殊原因吗?
附:我知道ES6中有更新的选择,但我很想知道这一点。
更新:我知道rejectHandler和catch是如何工作的。问题是为什么我看到更多的人只使用了rejectHandler和catch?这是最佳做法还是有一些优势?
更新(在这里添加答案):找到我正在寻找的第一手答案。
原因不仅仅是因为拒绝错误是由catch处理的,主要是因为链接。当我们链接promise.then.then.then然后,有了决心,拒绝模式证明链接它有点棘手,因为你不想实现拒绝处理程序只是为了将rejectData转发到链上。仅使用promise / then / catch以及resolve / return / throw证明在链接N个数据时非常有用。
@ Bob-Fanger(接受的答案)也解决了部分问题。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | getData(id) { return service.getData().then(dataList => { const data = dataList.find(data => { return data.id === id; }); if (!data) { // If I use Promise.reject here and use a reject handler in the parent then the parent might just be using the handler to route the error upwards in the chain //If I use Promise.reject here and parent doesn't use reject handler then it goes to catch which can be just achieved using throw. throw { code: 404, message: 'Data not present for this ID' }; } return configuration; }); } //somewhere up the chain ....getConfiguration() .then(() => { //successful promise execution }) .catch(err => { if (err.code) { // checked exception send(err); } else { //unchecked exception send({ code: 500, message: `Internal Server error: ${err}` }); } }); |
使用这些我需要担心的是promise / then / catch以及在链中的任何地方的resolve / return / throw。
不同之处在于,如果在resolveHandler中发生错误,则rejectHandler将不会处理该错误,只会处理原始promise中的拒绝。
rejectHandler并没有与catch一起使用,因为大多数时候我们只关心那些出错的地方。
仅创建一个错误处理程序使代码更容易推理。
如果链中的特定promise应该以不同的方式处理,这可能是使用rejectHandler的原因,但在这种情况下我可能会写一个
两者都没有比另一个更有用。当抛出错误或拒绝承诺时,都会调用被拒绝的处理程序和catch回调。
没有"最佳实践"使用一个而不是另一个。您可能会看到代码使用其中一个,但它的使用将基于代码需要实现的内容。程序员可能希望在链中的不同时间捕获错误,并处理在不同时间以不同方式抛出的错误。
希望以下内容有助于解释我的意思:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | somePromise .then( function() { /* code when somePromise has resolved */ }, function() { /* code when somePromise has thrown or has been rejected. An error thrown in the resolvedHandler will NOT be handled by this callback */ } ); somePromise .then( function() { /* code when somePromise has resolved */ } ) .catch( function() { /* code when somePromise has thrown or has been rejected OR when whatever has occurred in the .then chained to somePromise has thrown or the promise returned from it has been rejected */ } ); |
请注意,在第一个片段中,如果已解析的处理程序抛出,则没有可以捕获错误的拒绝处理程序(或
如帖子中所述,在对
因为拒绝处理程序返回而不抛出错误会恢复promise链的已填充通道,如果先前的拒绝处理程序正常返回,则不会调用最终的catch处理程序。
然后问题转变为用例,开发成本和知识水平。
用例
理论上,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | async function() { let retries = 3; let failureErr = null; while( retries--) { try { var result = await retryableOperationPromise() return result; } catch( err) { failureErr = err; } } throw failureErr // no more retries } |
其他用例可能不普遍。
开发成本或商业决策。
如果告诉用户稍后重试是可以接受的,那么对于承诺拒绝的具体原因做任何事情可能会更便宜。例如,如果我尝试在午夜预订航班,当航空公司提高价格时,我通常会被告知"发生了错误,请稍后再试",因为我在预订开始时给出的价格将不会受到尊重。
知识(<意见>)
我怀疑承诺的使用通常可以基于示例而不是对主题的深入了解。程序经理也希望为经验不足的开发人员保持代码库尽可能简单(可能是成本问题)。
如果使用有效,"最佳实践"可能无法真正适用于如何使用承诺的决策。一些开发人员和管理人员将原则上避免某些形式的使用,但并不总是基于技术优点。