标签:item var 进入 isp 效率 none event 任务 没有
1. js语言是单线程语言,主线程是单线程。
2. js语言采用事件循环(EventLoop)机制。
同步任务: 不被引擎挂起,在主线程等待执行的, 按照顺序执行的任务。
异步任务: 一般比较消耗时间,被引擎挂起,进入任务队列,等待主线程全部执行完才能执行的任务。
同步任务在主线程执行,异步任务进入任务队列,当主线程任务全部执行完成后,js引擎去查看异步任务队列,
如果满足条件,第一个异步任务进入主线程,变成同步任务。
再次全部执行完同步任务,然后继续查看任务队列,如此往复循环,直到队列为空,程序结束。
异步操作只是手动的实现改变函数的调用顺序。不会进入任务队列。
常见的异步操作是回调函数/事件监听模式/发布订阅模式;
异步操作又可以分为串行异步/并行异步/串并行结合异步;
普通回调函数只是改变了函数的执行顺序,并不会异步任务,也不会进入任务队列。
function a(callback){ callback(); // 回调函数 } function b(){} a(b); // b是a的回调函数
事件监听函数也是指定任务的执行顺序,不会进入任务队列。
<button>click</button> <script> function a() { let button = document.querySelector(‘button‘); button.click(); //函数a触发监听事件 } function b() {// 在a执行触发后,再执行 console.log("triggered by a");
// 最后需要取消监听 } document.addEventListener(‘click‘, b); </script>
任务执行后向“消息中心”发布(publish)消息, 其他任务订阅(subscribe)消息。
// 伪代码 function a() { XXX.publish(‘done‘); // 发布消息;XXX表示消息中心 } function b() {} // a发布后引发b执行 XXX.subscribe(‘done‘, b);// b订阅消息 // 如果b执行完,需要取消订阅!!! XXX.unSubscribe(‘done‘, f2);
有两种实现方式:
1)回调函数--逐级嵌套
下次执行等待上次执行结束,彼此之间有耦合。setTimeout是异步任务,会进入任务队列。
示例: 执行6次回调后执行final函数
<script> function asyncFn(arg, callback) { console.log("参数:", arg); setTimeout(function(){ callback(arg*2); }, 1000); } function final(value) { console.log("the final value equals ", value) } asyncFn(1, function(result) { asyncFn(result, function(result1) { asyncFn(result1, function(result2) { asyncFn(result2, function(result3){ asyncFn(result3, function(result4){ asyncFn(result4, function(result5){ final(result5); }) }) }) }) }) }) console.log(‘00‘) </script>
执行结果如下:
参数:1 00 参数:2 参数:4 参数:8 参数:16 参数:32 the final value equals 64
2)自定义一个函数(递归函数)
<script> let items = [...new Array(6)].fill(1); function asyncFn(arg, callback) { console.log("参数:", arg); setTimeout(function(){ callback(arg*2); }, 1000); } function final(value) { console.log("the final value equals ", value) } // 串行执行异步操作 var paramValue = 1; // 初始化参数 function serious(items) { if (items.shift()) { asyncFn(paramValue, function(result) { paramValue = result; serious(items); }) } else { final(paramValue) } } serious(items); console.log(‘00‘) </script>
执行结果和上面一样。
两种方式的执行结果都是6秒。
并行执行的异步函数,彼此之间不存在执行先后顺序问题,没有耦合。
几个异步函数同时执行,等待6个异步操作都执行完成后,执行final。
<script> let items = [...new Array(6)].fill(1); function asyncFn(arg, callback) { console.log("参数:", arg); setTimeout(function(){ callback(arg*2); }, 1000); } function final(value) { console.log("the final value equals ", value) } var result=[]; items.forEach((item, index) => [ asyncFn(index+1, function(res) { result.push(res); if (result.length === 6) { // 判断6个异步都执行完成 final(res); } }) ]) </script>
执行结果如下:
参数:1 参数:2 参数:3 参数:4 参数:5 参数:6 the final value equals 12
并行执行完成耗时1秒
串行异步操作耗时较多;并行效率,但是占用资源多,如果并行操作过多,很容易耗尽系统资源。
可以通过限制并行的个数来提高效率的同时,避免过分占用资源。
示例: 保证每次同时执行的异步任务是3个,等6个异步操作执行完成后执行final
<script> function asyncFn(arg, callback) { console.log("参数:", arg); setTimeout(function(){ callback(arg*2); }, 1000); } function final(value) { console.log("the final value equals ", value) } let items = Array.from(new Array(6), (_,index)=> index+1); let result=[]; let limit = 3; //最大3个 let running = 0; // 正在执行的个数 function both() { while(running < limit && items.length > 0){ let item = items.shift(); asyncFn(item, function(result) { running--; if (items.length > 0) { both(); } else if (running ===0 ) { // 执行完毕 final(result) } }) running++; } } both(); </script>
执行结果同上。
耗时2秒
标签:item var 进入 isp 效率 none event 任务 没有
原文地址:https://www.cnblogs.com/lyraLee/p/11734159.html