关于promise then的问题

发布于 2022-09-12 01:37:09 字数 434 浏览 15 评论 0

let p1=new Promise(resolve=>{
    resolve()
})
let p2=p1.then(data=>{
    return p2
}).then(res=>{
    console.log(res,'res')
})

为什么这样promise什么输出都没 也没有报错


let p1=new Promise(resolve=>{
    resolve()
})
let p2=p1.then(data=>{
    return p2
})

这样就会报错
Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凡尘雨 2022-09-19 01:37:09
let p2=p1.then(data=>{return p2;}).then(res=>{console.log(res,'res');})
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -> pp1
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -> pp2

then 会返回一个 promise ,这个 promise 使用它的回调的返回值来 resolve 的。

所以在上面,p1.then 返回的 pp1 ,是用 p2 resolve 的。
pp1.then 返回的 pp2 ,也就是 p2 ,是用回调返回的 undefined resolve 。

而,p2 是一个 promise 。所以,pp1 要等 p2 resolve 了它自己才能 resolve ,然后才能调用 pp1.then 的回调。
同时,p2 要等 pp1.then 的回调被调用并返回之后才能 resolve 。
于是互相等,谁也 resolve 不了。死锁。pp1.then 的回调不会被调用。

let p2=p1.then(data=>{return p2;})
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -> p2

这个就是用 p2 resolve p2 了。javascript 规定自己resolve自己是一个运行时错误 TypeError

浅唱ヾ落雨殇 2022-09-19 01:37:09

使用有错误,promise返回自身会死循环。
一个promise对象只能是三种三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败),并且不可逆,当标记成完成后,promise就结束了。
正确用法是。

let p1 = new Promise(resolve => {
    setTimeout(() => {
        resolve(Date.now())
    })
})
p1.then(data => {
    return data
}).then(data => {
    return data
}).then(data => {
    console.log('完成')
})

promise里不能返回promise本身,会造成无限循环。
至于promise返回自身后再追加then不报错,我猜测是因为promise实现代码中的逻辑是在执行promise的时候判断是否是Promise对象,如果是Promise就判断状态,状态时pending,就继续执行,如果有then、catch、finally方法就执行这些方法把promise的状态更改掉,循环就结束了。
但是如果没有thencatchfinally这些方法,那就可能会死循环,所以Promise的源码可能做了检查然后报出了这个错误提示,或者没有做检查,真的是运行时报的这个错。
我没有在V8的源码里找到相关的逻辑,下面是我的推测的伪代码,供参考

const PENDING = Symbol('PENDING');
const FULFILLED = Symbol('FULFILLED');
const REJECTED = Symbol('REJECTED');

…………

if (promise instanceof Promise) {
    // 判断状态
    if(this._status !== PENDING) {
        return;
    }
    try{
        // 标记状态
        promise.then(reject, resolve)
    } catch {
        // 标记状态
        …………
    } finally {
        …………
    }
}

then() {
    this.status = FULFILLED
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文