我正在阅读标题为“你不了解JS:ES6& amp;”的第4章。除了”
我知道Promise.resolve(..)在将可执行或立即值传递给此静态函数时会发生什么。
但如果它转到那个Promise.resolve(it.throw(err))
呢?
整个代码说明了承诺+生成器模式,如:
function run(gen) {
var args = [].slice.call( arguments, 1), it;
it = gen.apply( this, args );
return Promise.resolve()
.then( function handleNext(value){
var next = it.next( value );
return (function handleResult(next){
if (next.done) {
return next.value;
}
else {
return Promise.resolve( next.value )
.then(
handleNext,
function handleErr(err) {
return Promise.resolve(
it.throw( err )
)
.then( handleResult );
}
);
}
})( next );
} );
}
我的主要问题是拒绝处理程序 - function handleErr(err){..}
如果承诺链不断发展,它将如何运作以及将会发生什么。
答案 0 :(得分:2)
但如果它转到那个
Promise.resolve(it.throw(err))
呢?
it.throw(..)
的结果是IteratorResult对象:{ value: .., done: true }
,与it.next(..)
的结果相同。我将该对象包装在Promise.resolve(..)
的承诺中,以便在下一个刻度执行{{1>}时将对象值传回handleResult(..)
强>
@Bergi评论中建议的不仅仅是.then(handleResult)
的原因是因为这会在此刻度上执行return handleResult(it.throw(err))
,这不是我们想要的(用于调用堆栈目的) )。
仅当
handleResult(..)
它是如何运作的,如果承诺链继续发展将会发生什么。
function handleErr(err){..}
(通过handleErr(..)
取消)是最终被拒绝的承诺时,才会调用{p> next.value
。例如:
Promise.resolve(next.value)
此处,被拒绝的承诺位于run(function*(){
yield Promise.reject(42);
});
来自第一个next.value
来电,it.next(..)
只是将其作为被拒绝的承诺,Promise.resolve(next.value)
导致{使用被拒绝的then(handleNext,handleErr)
值调用{1}}。
现在,handleErr(..)
尝试将此异常值(42
)返回到生成器中,以防生成器中的某些等待it.throw(err)
捕获它。
例如,如果我们的生成器确实有42
,就像这样:
try..catch
...然后会捕获try..catch
异常,然后run(function*(){
try {
yield Promise.reject(42);
}
catch (err) {
return 10;
}
});
会发生。因此,42
调用将正常返回return 10
。
现在,it.throw(..)
会将其提升为正常履行的承诺,并在下一个标记处调用{ value: 10, done: true }
,并将该对象作为其Promise.resolve(..)
参数。 handleResult(..)
传递,next
返回if (next.done)
,返回通过递归的promise链,直到最终解析最初的return next.value
调用返回。
但是,由于我们的原始生成器不有10
,当run(..)
发生时,它抛出的异常会立即退出,异常中止当前{ {1}}致电。由于try..catch
由it.throw(next.value)
启动,handleErr(..)
将该异常提升为被拒绝的承诺,该承诺通过递归承诺链返回,最终拒绝原始调用{{{}的最外层承诺。 1}}返回。