js运行机制

本文最后更新于:2022年3月30日 下午

ref:javascript 运行机制 EventLoop

JS 的单线程

JavaScript 的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript 的主要用途是与用户互动,以及操作 DOM。这决定了它只能是单线程,保证执行任务的有序并避开复杂的同步问题。

EventLoop

  • js 是单线程运行的
  • 浏览器是多线程的

在代码执行的时候,通过将不同函数的执行上下文压入执行栈中来保证代码的有序执行。如果遇到了异步任务,js 引擎并不会一直等待其返回结果,而是会将这个事件的回调放入任务队列,继续执行执行栈中的其他任务。当执行栈清空后,再去任务队列读取异步函数的回调加入执行栈中执行。

  • 事件循环

    1. js同一时间只能执行一个任务,在这期间可能推入多个执行上下文
    2. 执行同步函数
    3. 将异步函数将其回调分别加入宏任务队列微任务队列
    4. 执行栈为空后(同步函数执行完),读取微任务队列执行
    5. 执行栈为空后,读取宏任务队列执行
    6. 执行栈为空后,如果该宏任务继续产生微任务则需要执行完新的微任务
      1. 执行完本轮任务

任务队列

异步任务通过任务队列来管理,任务被分为两类:微任务(micro task)和宏任务(macro task

  • 微任务(js引擎自己发起的任务)包括 process.nextTickpromise.thencatch,finallyMutationObserver

    • NOTE:nextTick会提升到微任务队列的栈顶
    • NOTE:遇到 await时,对await右侧进行计算,接着先去去执行async外部的同步函数,后再回到async函数中
  • 宏任务(宿主环境[浏览器,node]下发的任务)包括 setTimeoutsetIntervalsetImmediateI/O操作 ,UI渲染

面试题

  1. ```javascript
    // 1
    console.log(“script start”); // 1

    setTimeout(function () {

     console.log("setTimeout"); // 4
    

    }, 0);

    Promise.resolve()

     .then(function () {
         console.log("promise1"); //2
     })
     .then(function () {
         console.log("promise2"); //3
     });
    
    
    1.  ```javascript
        // 2
        console.log("1"); //1
    
        setTimeout(function () {
        	console.log("2"); // 5
        	process.nextTick(function () {
        		console.log("3"); //7
        	});
        	new Promise(function (resolve) {
        		console.log("4"); //6
        		resolve();
        	}).then(function () {
        		console.log("5"); //8
        	});
        });
        process.nextTick(function () {
        	console.log("6"); //3
        });
        new Promise(function (resolve) {
        	console.log("7"); //2
        	resolve();
        }).then(function () {
        	console.log("8"); //4
        });
    
        setTimeout(function () {
        	console.log("9"); //9
        	process.nextTick(function () {
        		console.log("10"); //11
        	});
        	new Promise(function (resolve) {
        		console.log("11"); //10
        		resolve();
        	}).then(function () {
        		console.log("12");
        	}); //12
        });
  2. ```javascript
    // 3
    async function async1() {

     console.log(1); //1
     new Promise(() => {
         console.log(2); //2
     });
     Promise.resolve().then(() => {
         console.log("异步3"); //6
     });
     console.log("同步3"); //3
    

    }

    Promise.resolve().then(() => {

     console.log(4); //5
    

    });

    setTimeout(() => {

     console.log(5); //7
    

    });

    async1();

    console.log(6); //4

    
    1.  ```javascript
        setTimeout(function () {
        	console.log("定时器开始啦");
        });
    
        new Promise(function (resolve) {
        	console.log("马上执行for循环啦");
        	for (var i = 0; i < 10000; i++) {
        		i == 99 && resolve();
        	}
        }).then(function () {
        	console.log("执行then函数啦");
        });
    
        console.log("代码执行结束");
    
        // 马上执行for循环啦
        // 代码执行结束
        // 执行then函数啦
        // 定时器开始啦
  3. ```javascript
    setTimeout(function () {

     console.log("setTimeout");
    

    });

    new Promise(function (resolve) {

     console.log("promise");
     resolve();
    

    }).then(function () {

     console.log("then");
    

    });

    console.log(“console”);

    // promise
    // console
    // then
    // setTimeout

    
    1.  ```javascript
        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 () {
        	process.nextTick(function () {
        		console.log("10");
        	});
        	new Promise(function (resolve) {
        		resolve();
        	}).then(function () {
        		console.log("12");
        	});
        });
  4. ```javascript
    setTimeout(() => {

     console.log(1);
    

    }, 0);
    Promise.resolve().then(() => {

     console.log(2);
    

    });
    console.log(3);

    // 3 2
    // 1

    
    1.  ```javascript
        setTimeout(() => {
        	console.log(1);
        }, 0);
        let a = new Promise((resolve) => {
        	console.log(2);
        	resolve();
        })
        	.then(() => {
        		console.log(3);
        	})
        	.then(() => {
        		console.log(4);
        	});
        console.log(5);
    
        // 2 5 3 4
        // 1
  5. ```javascript
    let a = new Promise((resolve) => {

     console.log(2);
     resolve();
    

    }).then(() => {

     console.log(5);
    

    });
    a.then(() => {

     console.log(3);
    

    });
    a.then(() => {

     console.log(4);
    

    });

    // 2 5 3 4

    
    1.  ```javascript
        new Promise((resolve, reject) => {
        	console.log("promise1");
        	resolve();
        })
        	.then(() => {
        		console.log("then11");
        		new Promise((resolve, reject) => {
        			console.log("promise2");
        			resolve();
        		})
        			.then(() => {
        				console.log("then21");
        			})
        			.then(() => {
        				console.log("then23");
        			});
        	})
        	.then(() => {
        		console.log("then12");
        	});
    
        // promise1,then11,promise2,then21,then12,then23
  6. ```javascript
    new Promise((resolve, reject) => {

     console.log("promise1");
     resolve();
    

    })

     .then(() => {
         console.log("then11");
         return new Promise((resolve, reject) => {
             console.log("promise2");
             resolve();
         })
             .then(() => {
                 console.log("then21");
             })
             .then(() => {
                 console.log("then23");
             });
     })
     .then(() => {
         console.log("then12");
     });
    

    // promise1 then11 promise2 then21 then12 then23

    
    1.  ```javascript
        new Promise((resolve, reject) => {
        	console.log("promise1");
        	resolve();
        })
        	.then(() => {
        		console.log("then11");
        		new Promise((resolve, reject) => {
        			console.log("promise2");
        			resolve();
        		})
        			.then(() => {
        				console.log("then21");
        			})
        			.then(() => {
        				console.log("then23");
        			});
        	})
        	.then(() => {
        		console.log("then12");
        	});
        new Promise((resolve, reject) => {
        	console.log("promise3");
        	resolve();
        }).then(() => {
        	console.log("then31");
        });
    
        //promise1 promise3 then11 promise2 then31 then21 then12 then23
  7. ```javascript
    async function async1() {

     console.log("async1 start");
     await async2();
     console.log("async1 end");
    

    }

    async function async2() {

     console.log("async2");
    

    }

    console.log(“script start”);

    setTimeout(function () {

     console.log("settimeout");
    

    }, 0);

    async1();

    new Promise(function (resolve) {

     console.log("promise1");
     resolve();
    

    }).then(function () {

     console.log("promise2");
    

    });
    console.log(“script end”);

    // script start,async1 start,async2,promise1,script end,async1 end,promise2
    // settimeout

    
    1.  ```javascript
        async function async1() {
        	console.log("async1 start"); // 2
        	await async2();
        	console.log("async1 end"); //  7
        }
    
        async function async2() {
        	console.log("async2"); // 3
        }
    
        console.log("script start"); // 1
    
        setTimeout(function () {
        	console.log("settimeout");
        });
    
        async1();
    
        new Promise(function (resolve) {
        	console.log("promise1"); //4
        	resolve();
        }).then(function () {
        	console.log("promise2"); // 8
        });
    
        setImmediate(() => {
        	console.log("setImmediate");
        });
    
        process.nextTick(() => {
        	console.log("process"); // 6
        });
    
        console.log("script end"); // 5
    
        //script start,async1 start,async2,promise1,script end,process,async1 end,promise2
        //sttimeout,setImmediate

js运行机制
http://yoursite.com/2022/02/24/js事件循环/
作者
tatekii
发布于
2022年2月24日
许可协议