1,js的异步
1.1)异步有哪些
ajax,事件,定时器,node读取文件
1.2)事件循环队列
在遇到js的异步执行的时候,js会把需要执行的代码根据异步的顺序放入一个事件循环队列,就是event loop,其中每个事件的代码需要执行完成,才会执行下一个事件的代码,比如同时发起三个请求A,B,C,属于异步的,但是根据请求返回的事件时间不同,会依次添加到事件队列中,如果B先返回,就把B的事件存入事件队列中,然后取出B对应的回调函数执行,如果在执行B的回调函数的时候,C返回了,会把C的事件存入事件队列中,如果再遇到A返回事件,也会存入事件队列中,根据事件队列中的循序,B的对应代码执行完成以后,就会执行C的代码,C完全执行完成以后,再执行B的代码。这个就是js的异步和事件循环队列。
在工作中,遇到过一个情况,有一个页面框架,需要请求几个js文件显示对应的卡片,所以同时异步的发起三个请求js文件的请求,每遇到一个js文件返回,就执行这个js文件,显示对应的卡片,所以是分别的一个一个显示卡片,而不能同时显示三张卡片,因为三个卡片的代码分别放在不同的js文件中,一定会一个js文件一个js文件的执行。
1.3)地狱回调
$.ajax({url: 'http://127.0.0.1:7001/test/ok',success: function (res) {console.log('--res', res)$.ajax({url: 'http://127.0.0.1:7001/test/ok',success: function (res) {console.log('--res', res)$.ajax({url: 'http://127.0.0.1:7001/test/ok',success: function (res) {console.log('--res', res)}})}})}})
1.4)Promise
let p1 = new Promise((resolve, reject) => {$.ajax({url: 'http://127.0.0.1:7001/test/ok',success: function (res) {console.log('--res p1---', res)resolve(res)}})})let p2 = new Promise((resolve, reject) => {$.ajax({url: 'http://127.0.0.1:7001/test/ok',success: function (res) {console.log('--res p2 ---', res)resolve(res)}})})let p3 = new Promise((resolve, reject) => {$.ajax({url: 'http://127.0.0.1:7001/test/ok',success: function (res) {console.log('--res p3 ---', res)resolve(res)}})})p1.then((res) => {console.log('eeee then -----p1 ', res)return p2}).then(res => {console.log('eeee then -----p2 ', res)return p3}).then(res => {console.log('eeee then -----p3 ', res)})
1.5)axios封装
let axios = new Promise((resolve, reject) => {$.ajax({url: 'http://127.0.0.1:7001/test/ok',success: function (res) {console.log('--res p3 ---', res)resolve(res)}})})document.getElementById('btn').onclick = function () {axios.then(res => {console.log('res axios', res)})}
1.6)async 和 awite
let axios = new Promise((resolve, reject) => {$.ajax({url: 'http://127.0.0.1:7001/test/ok',success: function (res) {console.log('--res p3 ---', res)resolve(res)}})})document.getElementById('btn').onclick = async function () {let res = await axiosconsole.log('res axios await -----', res)}
1.7)async/awite 原理
能理解 Generator 和 yield 的使用,但是还是不能理解如何用在async 里面的。
1.8)Promise顺序
1.8.1)Promise的异步顺序
在new Promise的时候,这个代码会立即执行,但是 .then 里面的代码是异步执行
let axios = new Promise((resolve, reject) => {console.log('Promise run right now')$.ajax({url: 'http://127.0.0.1:7001/test/ok--',success: function (res) {console.log('--res p3 ---', res)resolve(res)},error: (err) => {console.log('err', err)reject(err)}})})// axios.then(res => {// console.log('axios then', res)// }).catch(err => {// console.log('err catch', err)// })
new Promise 里面的 console.log(‘Promise run right now’) 和 ajax 会马上执行,
即使没有调用 ajax.then 代码依旧已经执行,所以new Promise的代码就是马上执行的。
1.8.2)所以打印的顺序是 1,2,3,因为 new Promise的代码是同步的
console.log(1)new Promise((resolve, reject) => {console.log(2)})console.log(3)
1.9)宏任务和微任务
console.log(1)setTimeout(() => {console.log(2)}, 0)let p1 = new Promise((resolve, reject) => {console.log(3)resolve()}).then(() => {console.log(4)})console.log(5)// 1,3,5,4,2
1,什么是宏任务,微任务
宏任务:setTimeOut,setInterval,I/O操作
微任务:Promise,process.nextTick(nodejs语法)
2,微任务和宏任务执行的循序
先执行同步代码
再取出第一个宏任务执行,所有相关的微任务会在下一个宏任务之前全部执行完成
如果直接遇见就是先微后宏
所以上面例子的代码,new Promise就是微任务,所以先执行,setTimeOut就是宏任务,所以后执行。
例子1:
// 1,5,11,6,2,3,4,7,8,10,9console.log(1)setTimeout(function () {console.log(2)new Promise(function (resolve) {console.log(3)resolve()}).then(() => {console.log(4)})}, 0)new Promise(resolve => {console.log(5)resolve()}).then(() => {console.log(6)})setTimeout(() => {console.log(7)new Promise((resolve) => {console.log(8)resolve()}).then(() => {console.log(9)})console.log(10)}, 0)console.log(11)
例子2:
const first = () => {return new Promise(resolve => {console.log(3)let p = new Promise(resolve => {console.log(7)setTimeout(() => {console.log(5)resolve(6)}, 0)resolve(1)})resolve(2)p.then(arg => {console.log(arg)})})}first().then(arg => {console.log(arg)})console.log(4)// 3,7,4,1,2,5
2,Promise相关
2.1)Promise的catch 和 then
let p1 = () => {return new Promise((resolve, reject) => {$.ajax({url: 'http://127.0.0.1:7001/test/ok',success: function (res) {resolve(res)},error: function (err) {reject(err)}})})}let p2 = () => (new Promise((resolve, reject) => {$.ajax({url: 'http://127.0.0.1:7001/test/ok',success: function (res) {resolve(res)},error: function (err) {reject(err)}})}))let p3 = () => (new Promise((resolve, reject) => {$.ajax({url: 'http://127.0.0.1:7001/test/ok---',success: function (res) {resolve(res)},error: function (err) {reject(err)}})}))p1().then(p2).catch(err => {console.log('p2 error---- ', err)}).then(p3).then(() => {console.log('first then p3 done ---- ')}, err => {console.log('second then function', err)}).catch(err => {console.log('any error will be catch here ---- ', err)}).then(() => {console.log('done')})
1,连续的Promise,如果每一个Promise没有写catch,只有最后的一个写了catch,那么前面任何一个Promise报错,都会走到这个catch中,但是前面的报错的Promise后边的Promise 不会再执行
比如:
p1().then(p2).then(p3).then(() => {console.log(' p3 done ---- ')}).catch(err => {console.log('any error will be catch here ---- ', err)}).then(() => {console.log('done')})
如果p2出错,会直接到catch,但是不会执行p3,但是最后的done依旧会执行
2,如果每一个Promise 都有自己的catch,那么任何报错都会走到自己的catch中,并且不会影响后边的Promise执行
p1().then(p2).catch(err => {console.log('p2 error---- ', err)}).then(p3).catch(err => {console.log('p3 error---- ', err)}).catch(err => {console.log('any error will be catch here ---- ', err)}).then(() => {console.log('done')})
如果p2出错,会走p2的error,但是不会影响p3的执行,并且不会走 any error will be catch here,但是会走最后的 done
3,如果then有第二个函数参数,最近的Promise报错的时候,会走到第二个函数中
p1().then(p2).then(p3).then(() => {console.log('first then p3 done ---- ')}, err => {console.log('second then function', err)}).catch(err => {console.log('p3 error---- ', err)}).catch(err => {console.log('any error will be catch here ---- ', err)}).then(() => {console.log('done')})
p3有的then有两个函数参数,如果p3报错的时候,会走到第二个函数中,而不会走catch中,也不会走所有的 any error will be catch here,
但是任然会走 done
4,最后不管有几个 then的done,都会执行
p1().then(p2).then(p3).then(() => {console.log('first then p3 done ---- ')}).catch(err => {console.log('any error will be catch here ---- ', err)}).then(() => {console.log('done')}).then(() => {console.log('done')}).then(() => {console.log('done')}).then(() => {console.log('done')}).then(() => {console.log('done')}).then(() => {console.log('done')})
后边的6个done都会执行,因为所有的then都是异步串联的,所以都会执行。
