js执行机制(Promise以及setTimeout)以及Promise中对throw new error()的捕获

JS的执行机制(Promise以及setTimeout)

简单来说,javascript是一门单线程语言,所以javascript是按语句的执行顺序执行的。
虽然js是单线程,但是我们可以将任务分成两类
1.同步任务:需要执行的任务在主线程上排队,一次执行
2.异步任务:没有立马执行但是需要被执行的任务,放在 任务队列里面

除了广义的同步任务和异步任务,我们可以分的更加精细一点:
macro-task(宏任务):包括整体代码script,setTimeout,setInterval
micro-task(微任务):Promise,process.nextTick
不同的任务会进入到不同的event queue。比如setTimeout和setInterval会进入相同的Event Queue。

1.所有同步任务偶在主线程上执行,形成一个很执行栈
2.主线程之外,还存在一个任务队列(task queue)只要异步任务有了运行结果,就在“任务队列”之中放置一个事件。
3.一旦“执行栈”中的所有同步任务执行完毕,系统就会读取“任务队列”,看看里面有哪些事件。那些对应的异步任务,就结束等待状态,进入执行栈开始被执行。
4.主线程不断重复以上三步。
js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。

console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})

process.nextTick(function() {
    console.log('6');
})

new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})


// 1,7,6,8,2,4,3,5,9,11,10,12

分析一下
(1) 首先先执行console.log,然后将setTimeout放到宏任务event queue里面 记作 setTimeout 1 ,接着 看到 process.nextTick ,将其放到微任务里面 ,记作 process 1,然后 看到new promise 立即执行输出7 ,将里面的then 放到 微任务里面 记作 then 2, 继续,遇到 setTimeout 放到宏任务里面记作 setTimeout 2 。目前输出的是:1,7,
可以简单把上述过程理解为下图
立即执行:1、7
宏:set1、set2
微:pro1、then2

(2)OK, 接下来,开始判断是否有微任务,刚刚放入到微任务event queue的进入到主程序开始执行,process 1 , then 2 目前输出的是:6,8、
立即执行:6、8
宏:set1、set2
微:无

(3)接下来,微任务的event queue 空了,进行下一轮事件,将刚刚放到宏任务的 setTimeout 1 进入到主线程
立即执行:set1
宏:set2
微:

(4)遇到 console 立即执行, 遇到 process.nextTick 放到微任务 event queue 里面 记作 process1, 接着遇到 new Promise 立即执行, 将 then 放到event queue 里面 记作 then 2,OK,当前宏任务里的任务执行完了,判断是否有微任务,发现有 process1, then 2 两个微任务 , 一次执行 目前输出的是:2,4,3,5、
立即执行:2、4
宏:set2
微:3、5

(5)目前主线程里的任务都执行结束了,又开始第三轮事件循环,输出的是:9,11,10,12、

(注意: 以上所说只能是在浏览器中的执行顺序。)

另外,举例说明一下Promise里throw new Error,能不能被后面的reject回调或者catch捕获的问题。

1、把throw new Error语句放延时函数里,只会报错,不执行reject函数或者catch函数

 var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
            	throw new Error('nono') //这里主动抛出错误
	        }, 500);
    })
   .then(()=>{},(err)=>{
       console.log(1) //这里是reject时应该调用的函数,但是这里并没有执行,只会在控制台报错
       console.log(err) //根本不执行这里
   })
   .catch((err)=>{
       console.log(2) //这里catch都不执行
       console.log(err)
   })

2、而我不把throw new Error语句放延时函数里,就能在reject函数里执行

var promise = new Promise((resolve, reject) => {
	throw new Error('nono') //这里直接抛出错误,就能被后面的reject函数执行到
})
.then(()=>{},(err)=>{
  	console.log(1) //这里就执行了
  	console.log(err)
})
.catch((err)=>{
  	console.log(2)
  	console.log(err)
})

3、另外,不用throw new Error,而是直接reject(),不论是否放在延时函数里都能正常被捕获

var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('hehe')
    }, 500);
})
    .then(()=>{},(err)=>{
        console.log(1) //可以捕获
        console.log(err)
    })
    .catch((err)=>{
        console.log(2)
        console.log(err)
    })
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值