When is .then(success, fail) considered an antipattern for promises?
我看过《蓝鸟承诺》常见问题解答,其中提到
1 2 | some_promise_call() .then(function(res) { logger.log(res) }, function(err) { logger.log(err) }) |
这个例子似乎表明了以下正确的方法。
1 2 3 | some_promise_call() .then(function(res) { logger.log(res) }) .catch(function(err) { logger.log(err) }) |
有什么区别?
What's the difference?
以下是控制流程图:
要用同步代码表示它:
1 2 3 4 5 6 7 8 9 10 | // some_promise_call().then(logger.log, logger.log) then: { try { var results = some_call(); } catch(e) { logger.log(e); break then; } // else logger.log(results); } |
第二个
1 2 3 4 5 6 7 | // some_promise_call().then(logger.log).catch(logger.log) try { var results = some_call(); logger.log(results); } catch(e) { logger.log(e); } |
两者之间的差异是如此之大。
I don't quite understand its explanation as for the try and catch
其理由是,通常您希望在处理的每个步骤中捕获错误,并且不应在链中使用它。期望是您只有一个处理所有错误的最终处理程序,而当您使用"反模式"时,一些随后回调中的错误不会被处理。
然而,这个模式实际上非常有用:当您想要处理在这个步骤中发生的错误时,并且当没有发生错误时(即当错误不可恢复时),您想要做一些完全不同的事情。请注意,这是在分支您的控制流。当然,这有时是需要的。
What's wrong with this the following?
1
2 some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
你必须重复你的回拨。你更想要
1 2 3 4 5 6 7 | some_promise_call() .catch(function(e) { return e; // it's OK, we'll just log it }) .done(function(res) { logger.log(res); }); |
您也可以考虑为此使用
这两者并不完全相同。区别在于第一个示例不会捕获在您的
但是我相信你链接到的文本的要点是,与回调相比,
作为一个做了很多复杂的异步工作并碰到这样的角落的人,我真的建议避免这种反模式并使用单独的处理程序方法。
通过观察两者的优点和缺点,我们可以对哪一种情况适合做一个经过计算的猜测。这是实现承诺的两种主要方法。两者都有正负之分
Catch Approach
1 2 3 | some_promise_call() .then(function(res) { logger.log(res) }) .catch(function(err) { logger.log(err) }) |
优势
缺点
Success/Error Approach
1 2 3 | some_promise_call() .then(function success(res) { logger.log(res) }, function error(err) { logger.log(err) }) |
优势
歧化剂
简单解释:
在ES2018中
When the catch method is called with argument onRejected, the
following steps are taken:Let promise be the this value. Return ? Invoke(promise,"then", ? undefined, onRejected ?).
这意味着:
1 | promise.then(f1).catch(f2) |
等于
1 | promise.then(f1).then(undefiend, f2) |
不是用言语,而是好榜样。以下代码(如果第一个承诺已解决):
1 2 3 4 5 6 | Promise.resolve() .then ( () => { throw new Error('Error occurs'); }, err => console.log('This error is caught:', err) ); |
与以下内容相同:
1 2 3 4 5 6 7 8 9 | Promise.resolve() .catch ( err => console.log('This error is caught:', err) ) .then ( () => { throw new Error('Error occurs'); } ) |
但由于第一个承诺被拒绝,这是不相同的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Promise.reject() .then ( () => { throw new Error('Error occurs'); }, err => console.log('This error is caught:', err) ); Promise.reject() .catch ( err => console.log('This error is caught:', err) ) .then ( () => { throw new Error('Error occurs'); } ) |