一、浏览器是多进程的,JS是单线程的
二、进程、线程、协程
解释:单个CUP,可能有多个进程,但是单个CPU只能运行一个进程 ;一个进程可能有多个线程,并且一个进程的资源是多个线程共享的;一个线程里面可能有多个协程,一个线程同时只能执行一个协程,如果这个协程需要等待某些条件才可以完成,可以停止当前协程,利用这段时间去做其他事情。所以简单的比喻就是:CUP(工厂)、进程(车间)、线程(工人)、协程(具体的事情)
三、同步任务与异步任务
同步任务:a执行完才能执行b。同步可以理解为串行。
异步任务: 并行指的是多个任务可以同时执行,就是事件循环机制中进入任务队列的任务,排在异步任务后面的代码,不用等待异步任务结束会马上运行。
四、并行执行与串行执行
串行执行:a执行完才能执行b, 串行可以理解为同步。
串行执行例子
let items = [1, 2, 3, 4, 5, 6]; let results = []; function async(arg, callback) { console.log( '参数为 ' + arg + ' , 1秒后返回结果' ); setTimeout( function () { callback(arg * 2); }, 1000); } function final(value) { console.log( '完成: ' , value); } function series(item) { if (item) { async(item, function (result) { results.push(result); return series(items.shift()); }); } else { return final(results[results.length - 1]); } } series(items.shift()); |
并行执行: 这里先说一下并行和并发的细微区别(并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生),然后这里先不讨论这个时间颗粒度这个细微的差别,就先当做一样。并行有两种情况,一种是多线程的方式实现,一种是异步的方式实现。
并行执行例子
let items = [1, 2, 3, 4, 5, 6]; let results = []; function async(arg, callback) { console.log( '参数为 ' + arg + ' , 1秒后返回结果' ); setTimeout( function () { callback(arg * 2); }, 1000); } function final(value) { console.log( '完成: ' , value); } // forEach 并行执行 items.forEach( function (item) { async(item, function (result) { results.push(result); if (results.length === items.length) { final(results[results.length - 1]); } }) }); |
解释:在js这个单线程执行的情况下:其实我们就可以将 同步理解为串行, 异步理解为并行。
五、普通任务、宏任务、微任务
解释:普通任务:就是同步任务。宏任务、微任务都属于异步任务。在一个宏任务中执行顺序:同步任务>微任务>宏任务
六、异步操作
1、回调函数
回调函数的例子
function f1(callback) { // ... callback(); } function f2() { // ... } f1(f2); |
2、事件监听
事件监听的例子
function f1 () { // .... } btn.addEventListener( 'click' , f1); |
3、发布/订阅
发布者f1执行完,向事件中心发布一个信号jQuery.publish('done'),从而引发订阅者f2去执行它订阅的事件。f2
完成执行后,可以取消订阅jQuery.unsubscribe('done', f2);
发布订阅理解
// 订阅者f2 jQuery.subscribe( 'done' , f2); // 发布者f1 function f1() { setTimeout( function () { // ... jQuery.publish( 'done' ); }, 1000); } jQuery.unsubscribe( 'done' , f2); |
4、定时器
定时器异步执行,具体是个宏任务执行
定时器例子
console.log(1); setTimeout( 'console.log(2)' ,1000); console.log(3); |
5、生成器
generator函数就是协程的具体实现例子。
生成器例子
function * createIterator() { let first = yield 1; let second = yield first + 2; yield second + 3; } let iterator = createIterator(); console.log(iterator.next()); // 返回yield 后面表达式的值 console.log(iterator.next(4)); // 参数改变上一个yield后面表达式的值 console.log(iterator.next(5)); console.log(iterator.next()); |
6、promise对象
promise对象的resolve('success')或者reject('fail')调用then方法里面的回调,属于异步执行,具体来说是微任务执行
promise基本语法
const promise = new Promise((resolve, reject) => { console.log(1); // resolve的参数传给then的第一个参数 // reject('fail'); resolve( 'success' ); console.log(2); }) promise.then(res => { console.log( '1' , arguments); return [ 'success' ]; // return的值作为下一个then的第一个参数 }).then(res => { console.log( '2' , res); }). catch (err => { console.log( 'error' , err); }); console.log(4); //打印的结果:1,2,4,3 |
应用场景:封装一些嵌套调用转同步方式调用的例子,如下:
这两者的区别如下:第一种,相当于success指向的是promise.then()传入的那个函数,第二种,相当于success指向那个function(res){} ,然后再在这个函数里面调用promise.then()传入的那个函数
方式1和方式2封装的本质还原
// 还原部分 const wx = { checkSession({success}) { const p = { name: 123 }; success(p); } } // 方式1 const promise = new Promise((resolve) => { wx.checkSession({ success: resolve }); }) // 方式2 const promise = new Promise((resolve) => { wx.checkSession({ success: function (p){ resolve(p); } }); }) promise.then((p) => { console.log(p); }) |
7、async/await
await后面是个promise对象,await 后是reject,后序代码不会执行,后序代码执行,加try...catch
async、await例子
// 未加try...catch async function f() { await Promise.reject( 'error' ); console.log(1); await 100; } // 加try...catch async function f() { try { await Promise.reject( 'error' ); } catch (e) { console.log( 'hhhhhh' ); } finally { } console.log(1); await 100; } f(); |
js异步总结先到此!