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)地狱回调

  1. $.ajax({
  2. url: 'http://127.0.0.1:7001/test/ok',
  3. success: function (res) {
  4. console.log('--res', res)
  5. $.ajax({
  6. url: 'http://127.0.0.1:7001/test/ok',
  7. success: function (res) {
  8. console.log('--res', res)
  9. $.ajax({
  10. url: 'http://127.0.0.1:7001/test/ok',
  11. success: function (res) {
  12. console.log('--res', res)
  13. }
  14. })
  15. }
  16. })
  17. }
  18. })

1.4)Promise

  1. let p1 = new Promise((resolve, reject) => {
  2. $.ajax({
  3. url: 'http://127.0.0.1:7001/test/ok',
  4. success: function (res) {
  5. console.log('--res p1---', res)
  6. resolve(res)
  7. }
  8. })
  9. })
  10. let p2 = new Promise((resolve, reject) => {
  11. $.ajax({
  12. url: 'http://127.0.0.1:7001/test/ok',
  13. success: function (res) {
  14. console.log('--res p2 ---', res)
  15. resolve(res)
  16. }
  17. })
  18. })
  19. let p3 = new Promise((resolve, reject) => {
  20. $.ajax({
  21. url: 'http://127.0.0.1:7001/test/ok',
  22. success: function (res) {
  23. console.log('--res p3 ---', res)
  24. resolve(res)
  25. }
  26. })
  27. })
  28. p1.then((res) => {
  29. console.log('eeee then -----p1 ', res)
  30. return p2
  31. }).then(res => {
  32. console.log('eeee then -----p2 ', res)
  33. return p3
  34. }).then(res => {
  35. console.log('eeee then -----p3 ', res)
  36. })

1.5)axios封装

  1. let axios = new Promise((resolve, reject) => {
  2. $.ajax({
  3. url: 'http://127.0.0.1:7001/test/ok',
  4. success: function (res) {
  5. console.log('--res p3 ---', res)
  6. resolve(res)
  7. }
  8. })
  9. })
  10. document.getElementById('btn').onclick = function () {
  11. axios.then(res => {
  12. console.log('res axios', res)
  13. })
  14. }

1.6)async 和 awite

  1. let axios = new Promise((resolve, reject) => {
  2. $.ajax({
  3. url: 'http://127.0.0.1:7001/test/ok',
  4. success: function (res) {
  5. console.log('--res p3 ---', res)
  6. resolve(res)
  7. }
  8. })
  9. })
  10. document.getElementById('btn').onclick = async function () {
  11. let res = await axios
  12. console.log('res axios await -----', res)
  13. }

1.7)async/awite 原理

能理解 Generator 和 yield 的使用,但是还是不能理解如何用在async 里面的。

1.8)Promise顺序

1.8.1)Promise的异步顺序
在new Promise的时候,这个代码会立即执行,但是 .then 里面的代码是异步执行

  1. let axios = new Promise((resolve, reject) => {
  2. console.log('Promise run right now')
  3. $.ajax({
  4. url: 'http://127.0.0.1:7001/test/ok--',
  5. success: function (res) {
  6. console.log('--res p3 ---', res)
  7. resolve(res)
  8. },
  9. error: (err) => {
  10. console.log('err', err)
  11. reject(err)
  12. }
  13. })
  14. })
  15. // axios.then(res => {
  16. // console.log('axios then', res)
  17. // }).catch(err => {
  18. // console.log('err catch', err)
  19. // })

new Promise 里面的 console.log(‘Promise run right now’) 和 ajax 会马上执行,
即使没有调用 ajax.then 代码依旧已经执行,所以new Promise的代码就是马上执行的。

1.8.2)所以打印的顺序是 1,2,3,因为 new Promise的代码是同步的

  1. console.log(1)
  2. new Promise((resolve, reject) => {
  3. console.log(2)
  4. })
  5. console.log(3)

1.9)宏任务和微任务

  1. console.log(1)
  2. setTimeout(() => {
  3. console.log(2)
  4. }, 0)
  5. let p1 = new Promise((resolve, reject) => {
  6. console.log(3)
  7. resolve()
  8. }).then(() => {
  9. console.log(4)
  10. })
  11. console.log(5)
  12. // 1,3,5,4,2

1,什么是宏任务,微任务
宏任务:setTimeOut,setInterval,I/O操作
微任务:Promise,process.nextTick(nodejs语法)
2,微任务和宏任务执行的循序
先执行同步代码
再取出第一个宏任务执行,所有相关的微任务会在下一个宏任务之前全部执行完成
如果直接遇见就是先微后宏
所以上面例子的代码,new Promise就是微任务,所以先执行,setTimeOut就是宏任务,所以后执行。
例子1:

  1. // 1,5,11,6,2,3,4,7,8,10,9
  2. console.log(1)
  3. setTimeout(function () {
  4. console.log(2)
  5. new Promise(function (resolve) {
  6. console.log(3)
  7. resolve()
  8. }).then(() => {
  9. console.log(4)
  10. })
  11. }, 0)
  12. new Promise(resolve => {
  13. console.log(5)
  14. resolve()
  15. }).then(() => {
  16. console.log(6)
  17. })
  18. setTimeout(() => {
  19. console.log(7)
  20. new Promise((resolve) => {
  21. console.log(8)
  22. resolve()
  23. }).then(() => {
  24. console.log(9)
  25. })
  26. console.log(10)
  27. }, 0)
  28. console.log(11)

例子2:

  1. const first = () => {
  2. return new Promise(resolve => {
  3. console.log(3)
  4. let p = new Promise(resolve => {
  5. console.log(7)
  6. setTimeout(() => {
  7. console.log(5)
  8. resolve(6)
  9. }, 0)
  10. resolve(1)
  11. })
  12. resolve(2)
  13. p.then(arg => {
  14. console.log(arg)
  15. })
  16. })
  17. }
  18. first().then(arg => {
  19. console.log(arg)
  20. })
  21. console.log(4)
  22. // 3,7,4,1,2,5

2,Promise相关

2.1)Promise的catch 和 then

  1. let p1 = () => {
  2. return new Promise((resolve, reject) => {
  3. $.ajax({
  4. url: 'http://127.0.0.1:7001/test/ok',
  5. success: function (res) {
  6. resolve(res)
  7. },
  8. error: function (err) {
  9. reject(err)
  10. }
  11. })
  12. })
  13. }
  14. let p2 = () => (new Promise((resolve, reject) => {
  15. $.ajax({
  16. url: 'http://127.0.0.1:7001/test/ok',
  17. success: function (res) {
  18. resolve(res)
  19. },
  20. error: function (err) {
  21. reject(err)
  22. }
  23. })
  24. }))
  25. let p3 = () => (new Promise((resolve, reject) => {
  26. $.ajax({
  27. url: 'http://127.0.0.1:7001/test/ok---',
  28. success: function (res) {
  29. resolve(res)
  30. },
  31. error: function (err) {
  32. reject(err)
  33. }
  34. })
  35. }))
  36. p1()
  37. .then(p2)
  38. .catch(err => {
  39. console.log('p2 error---- ', err)
  40. })
  41. .then(p3)
  42. .then(() => {
  43. console.log('first then p3 done ---- ')
  44. }, err => {
  45. console.log('second then function', err)
  46. })
  47. .catch(err => {
  48. console.log('any error will be catch here ---- ', err)
  49. })
  50. .then(() => {
  51. console.log('done')
  52. })

1,连续的Promise,如果每一个Promise没有写catch,只有最后的一个写了catch,那么前面任何一个Promise报错,都会走到这个catch中,但是前面的报错的Promise后边的Promise 不会再执行
比如:

  1. p1()
  2. .then(p2)
  3. .then(p3)
  4. .then(() => {
  5. console.log(' p3 done ---- ')
  6. })
  7. .catch(err => {
  8. console.log('any error will be catch here ---- ', err)
  9. })
  10. .then(() => {
  11. console.log('done')
  12. })

如果p2出错,会直接到catch,但是不会执行p3,但是最后的done依旧会执行

2,如果每一个Promise 都有自己的catch,那么任何报错都会走到自己的catch中,并且不会影响后边的Promise执行

  1. p1()
  2. .then(p2)
  3. .catch(err => {
  4. console.log('p2 error---- ', err)
  5. })
  6. .then(p3)
  7. .catch(err => {
  8. console.log('p3 error---- ', err)
  9. })
  10. .catch(err => {
  11. console.log('any error will be catch here ---- ', err)
  12. })
  13. .then(() => {
  14. console.log('done')
  15. })

如果p2出错,会走p2的error,但是不会影响p3的执行,并且不会走 any error will be catch here,但是会走最后的 done

3,如果then有第二个函数参数,最近的Promise报错的时候,会走到第二个函数中

  1. p1()
  2. .then(p2)
  3. .then(p3)
  4. .then(() => {
  5. console.log('first then p3 done ---- ')
  6. }, err => {
  7. console.log('second then function', err)
  8. })
  9. .catch(err => {
  10. console.log('p3 error---- ', err)
  11. })
  12. .catch(err => {
  13. console.log('any error will be catch here ---- ', err)
  14. })
  15. .then(() => {
  16. console.log('done')
  17. })

p3有的then有两个函数参数,如果p3报错的时候,会走到第二个函数中,而不会走catch中,也不会走所有的 any error will be catch here,
但是任然会走 done

4,最后不管有几个 then的done,都会执行

  1. p1()
  2. .then(p2)
  3. .then(p3)
  4. .then(() => {
  5. console.log('first then p3 done ---- ')
  6. })
  7. .catch(err => {
  8. console.log('any error will be catch here ---- ', err)
  9. })
  10. .then(() => {
  11. console.log('done')
  12. })
  13. .then(() => {
  14. console.log('done')
  15. })
  16. .then(() => {
  17. console.log('done')
  18. })
  19. .then(() => {
  20. console.log('done')
  21. })
  22. .then(() => {
  23. console.log('done')
  24. }).then(() => {
  25. console.log('done')
  26. })

后边的6个done都会执行,因为所有的then都是异步串联的,所以都会执行。