第 13 题:Promise 构造函数是同步执行还是异步执行,那么 then 方法呢?

发布于 2022-07-22 21:47:45 字数 285 浏览 138 评论 38

const promise = new Promise((resolve, reject) => {
  console.log(1)
  resolve()
  console.log(2)
})

promise.then(() => {
  console.log(3)
})

console.log(4)

执行结果是:1243,promise 构造函数是同步执行的,then 方法是异步执行的。

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

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

发布评论

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

评论(38

止于盛夏 2022-05-04 13:57:32

then()到底是同步执行还是异步执行?为什么回答里有的说是同步有的说是异步

根据上面的回答,总结下应该是then函数本身是同步,then里面的cb是异步

原谅过去的我 2022-05-04 13:57:32

这里对上面的例子做一个扩展

const promise = new Promise((resolve, reject) => {
  console.log(1);
  resolve(5);
  console.log(2);
}).then(val => {
  console.log(val);
});

promise.then(() => {
  console.log(3);
});

console.log(4);

setTimeout(function() {
  console.log(6);
});

执行结果: 124536

债姬 2022-05-04 13:57:32

甜妞爱困 2022-05-04 13:57:32

只要好好理解下 Promise, 很多疑问会迎刃而解

抓重点理解Promise

深白境迁°sunset 2022-05-04 13:57:32

这里对上面的例子做一个扩展

const promise = new Promise((resolve, reject) => {
  console.log(1);
  resolve(5);
  console.log(2);
}).then(val => {
  console.log(val);
});

promise.then(() => {
  console.log(3);
});

console.log(4);

setTimeout(function() {
  console.log(6);
});

执行结果: 124536

请问在浏览器控制器中执行的时候,打印的3和6之间会有一个“随机数字”,它是怎么出现的,代表的什么呢?

木格〃 2022-05-04 13:57:32

这里对上面的例子做一个扩展

常量 承诺 =  新 无极((决心,拒绝)=> {
   控制台。日志(1);
   解析(5);
   控制台。日志(2);
})。然后(VAL  => {
   控制台。日志(VAL);
});

承诺。然后(()=> {
   控制台。日志(3);
});

控制台。log(4);

的setTimeout(函数(){
   控制台。日志(6);
});

执行结果:124536

请问在浏览器控制器中执行的时候,打印的3和6之间会有一个“随机数字”,它是怎么出现的,代表的什么呢?

随机数字是seTimeout方法的返回值
setTimeout()方法的返回值是一个 **唯一的数值 **
如果你想要终止setTimeout()方法的执行,那就必须使用 clearTimeout()方法来终止,而使用这个方法的时候,系统必须知道你到底要终止的是哪一个setTimeout()方法(因为你可能同时调用了好几个 setTimeout()方法),这样clearTimeout()方法就需要一个参数,这个参数就是setTimeout()方法的返回值(数值),
用这个数值来唯一确定结束哪一个setTimeout()方法。

ら。栖息 2022-05-04 13:57:32

这里对上面的例子做一个扩展

const promise = new Promise((resolve, reject) => {
  console.log(1);
  resolve(5);
  console.log(2);
}).then(val => {
  console.log(val);
});

promise.then(() => {
  console.log(3);
});

console.log(4);

setTimeout(function() {
  console.log(6);
});

执行结果: 124536
resolve(5)也能调用到下面这个then方法吗
promise.then(() => {
console.log(3);
});

妞丶爷亲个 2022-05-04 13:57:32

promise是微观任务,setTimeout是宏观任务,先执行微观任务,在执行宏观任务;微观任务里,先执行同步再执行异步 所以结果是 124536

眼角的笑意。 2022-05-04 13:57:32

promise构造函数肯定是同步执行的,new Promise和其他的什么new Map、new Set一样的都是同步执行,当执行resolve方法将promise状态更新为fulfilled,并返回一个promise对象,调用then就会将then中的回调放入微任务队列中,也就是说promise.then才是异步

油焖大侠 2022-05-04 13:57:32

严格来说 构造函数 then都是同步的, 只是then内部的这个参数回调函数需要看resolve执行时机 并且内部做了个定时器, 所以回调才是异步的

猫七 2022-05-04 13:57:32

整体代码、setTimeout、setInterval、Promise构造函数是宏任务,promise的then方法是微任务

梨涡少年 2022-05-04 13:57:32

假如有这么一段代码

new Promise(resolve => {
    resolve(1);
    Promise.resolve().then(() => console.log(2));
    Promise.resolve().then(() => console.log(5));
}).then(t => console.log(t));

请问为什么输出结果是2,5,1呢?
resolve(1) 之后,不应该是优先注册了外部 .then 的回调吗?
还是说内部的 Promise 是同步执行的?

俏︾媚 2022-05-04 13:57:32

应该

假如有这么一段代码

new Promise(resolve => {
    resolve(1);
    Promise.resolve().then(() => console.log(2));
    Promise.resolve().then(() => console.log(5));
}).then(t => console.log(t));

请问为什么输出结果是2,5,1呢?
resolve(1) 之后,不应该是优先注册了外部 .then 的回调吗?
还是说内部的 Promise 是同步执行的?

当然是异步啦,在执行resolve()之前会先将其他语句执行完的

淡墨 2022-05-04 13:57:32

Promise对象,就是将异步操作以同步操作的流程表达出来

我的天。then当然也是同步执行,then方法的参数callback函数才会在then等待状态变化的promise fulfill或者reject后起一个微任务把callback丢进去

微暖i 2022-05-04 13:57:32

这题还不如直接问Promise的原理或写法

堇色安年?Search% 2022-05-04 13:57:32

.then()当然是同步执行,只不过是.then的cb被放入了微任务队列,产生了异步执行

更详细一点的说法是等到 promise变为 resolved状态的时候,then注册的回调函数才被放入到微任务队列中,等待调用执行

七禾 2022-05-04 13:57:32

.then()当然是同步执行,只不过是.then的cb被放入了微任务队列,产生了异步执行

更详细一点的说法是等到 promise变为 resolved状态的时候,then注册的回调函数才被放入到微任务队列中,等待调用执行

promise = new Promise((resolve, reject) => {
    console.log(1);
    setTimeout(() => {
        resolve(5);
    }, 10)
    console.log(2);
  }).then(val => {
    console.log(val);
  });
  
  promise.then(() => {
    console.log(3);
  });
  
  console.log(4);
  
  setTimeout(function() {
    console.log(6);
  });

补段代码

眼睛会笑i 2022-05-04 13:57:32

做戏做全套... 写一个更有助于理解

ps: 微任务以宏任务(setTimeout)替代

class PromiseA {
    constructor(fn) {
        this.status = 'pending';
        this.value = null;
        this.error = null;

        this.resolveArr = [];
        this.rejectArr = [];

        let resolve = (value) => {
            // 防止多次resolve
            if (this.status !== 'pending') return;
            setTimeout(()=>{
                this.value = value;
                this.status = 'fullfiled';
                // 派发过往订阅
                while(this.resolveArr.length) {
                    let tmp = this.resolveArr.shift();
                    tmp(value);
                }
            }, 0);
        }
        let reject = (err) => {
            // 防止多次reject
            if (this.status !== 'pending') return;
            setTimeout(()=>{
                this.status = 'rejected';
                this.error = err;
                // 派发过往订阅
                while(this.rejectArr.length) {
                    let tmp = this.rejectArr.shift();
                    tmp(err);
                }
            }, 0);
        }
        fn(resolve, reject);
    }
    then(fun1, fun2) {
        // 根据规范,如果then的参数不是function,则我们需要忽略它, 让链式调用继续往下执行
        (typeof fun1 !== 'function') && (fun1 = value => value)
        // 
        (typeof fun2 !== 'function') && (fun2 = error => {
            throw(error);
        })

        return new PromiseA((resolve, reject)=>{
            let resolveItem = (param) => {
                try {
                    let tmp = fun1(param);
                    tmp instanceof PromiseA ? tmp.then(resolve, reject) : resolve(tmp);
                } catch (e) {
                    reject(e);
                }
            }
            let rejectItem = (err) => {
                try {
                    let tmp = fun2(err);
                    tmp instanceof PromiseA ? tmp.then(resolve, reject) : resolve(tmp);
                } catch (e) {
                    reject(e);
                }
            }

            if (this.status == 'pending') {
                this.resolveArr.push(resolveItem);
                this.rejectArr.push(rejectItem);
            } else if (this.status == 'fullfiled') {
                resolveItem(this.value);
            } else if (this.status == 'rejected') {
                rejectItem(this.error);
            }
        });
    }
    catch(rejectFn) {
        return this.then(null, rejectFn);
    }
    finally(fn) {
        // 保证了fn执行在前.. 但是有点绕
        return this.then((param)=>{
            // 万一 fn reject了
            return PromiseA.resolve(fn()).then(()=>param, ()=>param);
        }, (err) =>{
            // 万一 fn reject了
            return PromiseA.resolve(fn()).then(()=>{
                throw err;
            }, ()=>{
                throw err;
            });
        })
    }
    static resolve(param) {
        if (param instanceof PromiseA) return param;
        return new PromiseA((resolve)=>{
            resolve(param);
        })
    }
    static reject(param) {
        if (param instanceof PromiseA) return param;
        return new PromiseA((resolve, reject)=>{
            reject(param);
        })
    }

    static all(arr) {
        return new PromiseA((resolve, reject)=>{
            let i = 0;
            let ret = [];
            while(arr.length) {
                let tmp = arr.shift();
                tmp.then((param)=>{
                    ret[i] = param;
                    i++
                    if (i == arr.length) {
                        resolve(ret);
                    }
                },(err) => {
                    reject(err);
                })
            }
        });
    }
    static race(arr) {
        // 只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。
        return new PromiseA((resolve, reject) => {
            arr.forEach((item)=>{
                // 状态变化是单向的
                item.then(resolve, reject);
            })
        })
    }
    // 允许reject X次 失败后Y秒继续触发
    static retry(fn, x, y) {
        return PromiseA((resolve, reject)=>{
            let failTimes = 0;
            // 也可以把历代err保存起来
            // let errArr = [];

            function cb () {
                fn().then(resolve).catch((err)=>{
                    if (failTimes == x) {
                        reject(err);
                        return;
                    }

                    setTimeout(()=> {
                        cb();
                    }, y);

                    failTimes++;
                });
            }
            cb();
        }) 
    }

    static promisefy (cb) {
        return (...arg)=>{
            return new Promise((reoslve, reject)=>{
                cb(...arg, reoslve);
            })
        }
    }
}
雨后彩虹 2022-05-04 13:57:32

promise 的构造函数是同步执行的,then方法也是同步执行的,只不过 then 里面的回调函数是异步执行的。

离线来电— 2022-05-04 13:57:32

同志们,这道题绝对没有你们想象的这么简单,补充一个不错的文章中的摘录:

在Promises/A+规范的Notes 3.1中提及了promise的then方法可以采用“宏任务(macro-task)”机制或者“微任务(micro-task)”机制来实现。所以开头提及的promise在不同浏览器的差异正源于此,有的浏览器将then放入了macro-task队列,有的放入了micro-task 队列。在jake的博文Tasks, microtasks, queues and schedules中提及了一个讨论vague mailing list discussions,一个普遍的共识是promises属于microtasks队列。

—— https://segmentfault.com/a/1190000038985579

以往的大感动 2022-05-04 13:57:32

const promise = new Promise(async (resolve, reject) => {
console.log(1)
await resolve()
console.log(2)
})

promise.then(() => {
console.log(3)
})

console.log(4);
碰到过这种扩展,想了解为什么2在3之前执行

腻橙味 2022-05-04 13:57:32

const promise = new Promise(async (resolve, reject) => {
console.log(1)
await resolve()
console.log(2)
})

promise.then(() => {
console.log(3)
})

console.log(4);
碰到过这种扩展,想了解为什么2在3之前执行

这种出现 await 的代码,你可以等价转化为:

const promise = new Promise(async (resolve, reject) => {
   console.log(1)
   Promise.resolve(resolve()).then(() => {
       console.log(2)
   })
})
promise.then(() => {
   console.log(3)
})

console.log(4);

也就是将 await 后面跟着的部分用一个 Promise.resolve() 包裹起来,然后剩余部分塞到一个 then 的回调函数里。这样再分析就简单了。

童话 2022-05-04 13:57:32

严格来说then方法 是同步执行的,then方法的参数(回调函数)是 异步执行的

疯到世界奔溃 2022-05-04 13:57:32

excutor执行器里面是同步执行的,then里面是异步操作

如何体现呢?能举例说明吗?

最单纯的乌龟 2022-05-04 13:57:32

之所以then是异步是为了处理循环引用的问题。

const p1 = promise1.then(value => {
    return p1
})

判断then里面new的promise 跟successCallback执行后得到的p1是不是同一个promise。
但是then里面处理回调的时候new的promise还没有创建完成。

空心空情空意 2022-05-04 13:56:46

then()到底是同步执行还是异步执行?为什么回答里有的说是同步有的说是异步

物价感观 2022-05-04 13:56:42

这个题和之前的第8题类似

花间憩 2022-05-04 13:55:58

.then()当然是同步执行,只不过是.then的cb被放入了微任务队列,产生了异步执行

故事和酒 2022-05-04 13:54:50

看过 Event Loop 基础原理的就明白,Promise构造函数是同步执行,而 .then .catch .啥啥的是异步(还有process.nextTick等等,大家可以查),
而且放到了微队列中,async/await 中,await 前面的是同步,await 后面的是异步,写法上是这样,但是其实是 语法糖,最后还会转为 Promise.then的形式

双手揣兜 2022-05-04 13:52:19

Promise 构造函数是同步执行,then 是异步执行。看一下 Promise 的实现就知道了。

牵你的手,一向走下去 2022-05-04 13:41:00

Promise必然是同步的。就then我补充一下:
在ES6时代有了微异步的设定,then作为最典型代表,算是异步的一员。
在ES5时代,实现then的方式则要看构造函数里resolve(或reject)的用法了,如果resolve被同步使用,实质上resolve仍然是同步的。

忘羡 2022-05-04 13:32:19

这里对上面的例子做一个扩展

const promise = new Promise((resolve, reject) => {
  console.log(1);
  resolve(5);
  console.log(2);
}).then(val => {
  console.log(val);
});

promise.then(() => {
  console.log(3);
});

console.log(4);

setTimeout(function() {
  console.log(6);
});

执行结果: 124536

请问为什么3在val之前?

3是在5后面打印出来的啊,第一轮事件循环的时候,microtask queue里面先添加的promise.resolve(5).then((val)=>{console.log(val)}),后添加的promise.then(() => {
console.log(3);
});

王权女流氓 2022-05-04 13:30:38

这里对上面的例子做一个扩展

const promise = new Promise((resolve, reject) => {
  console.log(1);
  resolve(5);
  console.log(2);
}).then(val => {
  console.log(val);
});

promise.then(() => {
  console.log(3);
});

console.log(4);

setTimeout(function() {
  console.log(6);
});

执行结果: 124536

请问为什么3在val之前?

莫多说 2022-05-04 13:26:23

excutor执行器里面是同步执行的,then里面是异步操作

_蜘蛛 2022-05-04 13:20:31

Promise new的时候会立即执行里面的代码 then是微任务 会在本次任务执行完的时候执行 setTimeout是宏任务 会在下次任务执行的时候执行

偷得浮生 2022-05-03 16:01:03

学习了

套路撩心 2022-05-02 10:15:01

这里对上面的例子做一个扩展

const promise = new Promise((resolve, reject) => {
  console.log(1);
  resolve(5);
  console.log(2);
}).then(val => {
  console.log(val);
});

promise.then(() => {
  console.log(3);
});

console.log(4);

setTimeout(function() {
  console.log(6);
});

执行结果: 124536

~没有更多了~

关于作者

一身骄傲

暂无简介

0 文章
0 评论
20 人气
更多

推荐作者

linfzu01

文章 0 评论 0

可遇━不可求

文章 0 评论 0

枕梦

文章 0 评论 0

qq_3LFa8Q

文章 0 评论 0

JP

文章 0 评论 0

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