尼采般地抒情

公告栏

此网站主题为本人手写主题, 主题待开源···

站点信息

文章总数目: 305
已运行时间: 1063
目录
  1. 一、JS代码执行机制
    1. JavaScript的单线程
    2. 同步任务和异步任务
    3. 事件循环机制
    4. 实例
  2. 异步编程
    1. Promise
    2. Async、await
    3. 综合
  3. 参考

尼采般地抒情

尼采般地抒情

公告栏

此网站主题为本人手写主题, 主题待开源···

站点信息

文章总数目: 305
已运行时间: 1063

一、JS代码执行机制

JavaScript的单线程

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

同步任务和异步任务

单线程导致的问题就是后面的任务等待前面任务完成,如果前面任务很耗时(比如读取网络数据),后面任务不得不一直等待!!

为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制。于是,JS 中出现了同步任务异步任务


JS中所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。

  • 【同步任务】指的是:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
  • 【异步任务】指的是:不进入主线程、而进入“任务队列”的任务,当主线程中的任务运行完了,才会将异步任务相关的回调函数从”任务队列”取出异步任务放入主线程执行。

异步任务又分为宏任务和微任务

宏任务

  • 主代码块
  • setTimeout
  • setInterval

微任务

  • process.nextTick ()
  • Promise
  • Object.observe

事件循环机制

  1. 碰到同步任务,就先执行执行栈中的同步任务

遇到函数的嵌套调用就把函数压入栈内再依次“剥洋葱”

  1. 碰到异步任务就压入任务队列(异步任务分为宏任务和微任务)
  2. 当前执行栈中的所有同步任务执行完毕,就将执行异步任务,异步任务执行原则“先微后宏”

由于主线程不断地重复获得任务、执行任务、再获取任务、再执行……,这种机制被称为事件循环(Event Loop)

实例

const promise = new Promise((resolve, reject) => {

// new 先行
console.log(1);
resolve("success");
console.log(2);
});
promise.then((data) => {
// 微任务
console.log(data);
console.log(3);
});
console.log(4);
1
2
4
success
3
const promise1 = new Promise((resolve, reject) => {
console.log("promise1");
resolve("resolve1");
});
const promise2 = promise1.then((res) => {
console.log(res);
});
console.log("1", promise1);
console.log("2", promise2);
promise1
1 Promise { 'resolve1' }
2 Promise { <pending> }
resolve1
测试代码
// setTimeout(()=>{
// console.log(1)
// },0)
// new Promise((resolve) =>{
// console.log(2)
// resolve()
// }).then(()=>{ // 此时将 then 的内容放到微任务队列,然后执行同步代码 5
// console.log(3)
// }).then(()=>{
// console.log(4)
// })
// console.log(5)

// setTimeout(() => {
// console.log('timer1');
// setTimeout(() => {
// console.log('timer3')
// }, 0)
// }, 0)
// setTimeout(() => {
// console.log('timer2')
// }, 0)
// console.log('start')

// setTimeout(() => {
// console.log('timer1');
// Promise.resolve().then(() => {
// console.log('promise')
// })
// }, 0)
// setTimeout(() => {
// console.log('timer2')
// }, 0)
// console.log('start')

// const first = () => (new Promise((resolve, reject) => {
// console.log(3)

// let p = new Promise((resolve, reject) => {
// 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) // 在 1 2 之前执行,此时 1 2 都在微任务队列里面

// setTimeout(() => {
// console.log("0")
// }, 0)

// new Promise((resolve,reject)=>{
// console.log("1")
// resolve()
// }).then(()=>{ // then 碰到 then,就将其全部放到微任务队列,再细致考虑
// console.log("2")
// new Promise((resolve,reject)=>{
// console.log("3")
// resolve()
// }).then(()=>{
// console.log("4") // 先 5 后 4 “队列”
// }).then(()=>{
// console.log("5")
// })
// }).then(()=>{
// console.log("6")
// })

// new Promise((resolve,reject)=>{
// console.log("7")
// resolve() //2
// }).then(()=>{
// console.log("8")
// })

// Promise.resolve().then(() => {
// console.log('promise1');
// const timer2 = setTimeout(() => {
// console.log('timer2')
// }, 0)
// });

// const timer1 = setTimeout(() => {
// console.log('timer1')
// Promise.resolve().then(() => {
// console.log('promise2')
// })
// }, 0)

// console.log('start');

// const promise1 = new Promise((resolve, reject) => {
// setTimeout(() => {
// resolve('success')
// }, 1000)
// })
// const promise2 = promise1.then(() => {
// throw new Error('error!!!')
// })

// console.log('promise1', promise1)
// console.log('promise2', promise2)

// setTimeout(() => {
// console.log('promise1', promise1)
// console.log('promise2', promise2)
// }, 2000)

异步编程

Promise

  • 理解并能准确判断代码执行时机
测试代码
/\*\*

- Promise:resolve reject then catch finally
  \*/
  // let p1 = new Promise((resolve, reject) => {
  // setTimeout(() => {
  // resolve('success')
  // },1000)
  // })

// let p2 = new Promise((resolve, reject) => {
// setTimeout(() => {
// reject('failed')
// }, 500)
// })

// Promise.race([p1, p2]).then((result) => {
// console.log(result)
// }).catch((error) => {
// console.log(error) // 打开的是 'failed'
// })

// function test(resolve, reject) {
// let timeOut = Math.random() _ 2;
// console.log('set timeout to: ' + timeOut + ' seconds.');
// setTimeout(function () {
// if (timeOut < 1) {
// console.log('call resolve()...');
// resolve('200 OK');
// }
// else {
// console.log('call reject()...');
// reject('timeout in ' + timeOut + ' seconds.');
// }
// }, timeOut _ 1000);
// }

// let p1 = new Promise(test);
// let p2 = p1.then(function (result) {
// console.log('成功:' + result);
// });
// let p3 = p2.catch(function (reason) {
// console.log('失败:' + reason);
// });

// function test(resolve, reject) {
// let timeOut = Math.random() _ 2;
// console.log('set timeout to: ' + timeOut + ' seconds.');
// setTimeout(function () {
// if (timeOut < 1) {
// console.log('call resolve()...');
// resolve('200 OK');
// }
// else {
// console.log('call reject()...');
// reject('timeout in ' + timeOut + ' seconds.');
// }
// }, timeOut _ 1000);
// }

// new Promise(test)
// .then(function (result) {
// console.log('成功:' + result);
// })
// .catch(function (reason) {
// console.log('失败:' + reason);
// })

// const promise = new Promise((resolve, reject) => {
// reject("error");
// resolve("success2"); // 需要 return 才能传递结果
// });
// promise.then(res => {
// console.log("then1: ", res); // 需要 return 才能往下传递结果
// }).then(res => {
// console.log("then2: ", res);
// }).catch(err => {
// console.log("catch: ", err);
// }).then(res => {
// console.log("then3: ", res); // undefined catch 也会返回 promise 对象
// })

// Promise.resolve(1)
// .then(res => {
// console.log(res);
// return 2; // return 2 会被包装成 resolve(2)
// })
// .catch(err => {
// return 3;
// })
// .then(res => {
// console.log(res);
// });

// const promise = new Promise((resolve, reject) => {
// setTimeout(() => {
// console.log('timer')
// resolve('success')
// }, 1000)
// })
// const start = Date.now();
// promise.then(res => {
// console.log(res, Date.now() - start)
// })
// promise.then(res => {
// console.log(res, Date.now() - start) // 两个字几乎一样,状态一旦改变,就不会在变动了
// })

// Promise.resolve().then(() => {
// return new Error('error!!!') // 被包裹成了 return Promise.resolve(new Error('error!!!'))
// }).then(res => {
// console.log("then: ", res)
// }).catch(err => {
// console.log("catch: ", err)
// })


/**
 * then链式调用
 */
// function runAsync1(){
//   var p = new Promise(function(resolve, reject){
//       //做一些异步操作
//       setTimeout(function(){
//           console.log('异步任务1执行完成');
//           resolve('随便什么数据1');
//       }, 2000);
//   });
//   return p;
// }
// function runAsync2(){
//   var p = new Promise(function(resolve, reject){
//       //做一些异步操作
//       setTimeout(function(){
//           console.log('异步任务2执行完成');
//           resolve('随便什么数据2');
//       }, 1000);
//   });
//   return p;
// }
// function runAsync3(){
//   var p = new Promise(function(resolve, reject){
//       //做一些异步操作
//       setTimeout(function(){
//           console.log('异步任务3执行完成');
//           resolve('随便什么数据3');
//       }, 1000);
//   });
//   return p;
// }

// runAsync1()
// .then(function(data){
// console.log(data);
// return runAsync2();
// })
// .then(function(data){
// console.log(data);
// return runAsync3();
// })
// .then(function(data){
// console.log(data);
// });


/**
 * all: 所有异步任务完成执行then
 * race:执行快的直接跳出
 */
//  function runAsync (x) {
//     const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000))
//     return p
// }
// Promise.all([runAsync(1), runAsync(2), runAsync(3)]) // 参数数组都是promise实例,如果不是强制包装
//   .then(res => console.log(res))

// function runAsync (x) {
// const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000))
// return p
// }
// function runReject (x) {
// const p = new Promise((res, rej) => setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 \* x))
// return p
// }
// Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)])
// .then(res => console.log(res))
// .catch(err => console.log(err))

// let p1 = new Promise((resolve, reject) => {
// setTimeout(() => {
// resolve('success')
// },1000)
// })

// let p2 = new Promise((resolve, reject) => {
// setTimeout(() => {
// reject('failed')
// }, 3000)
// })

// Promise.race([p1, p2]).then((result) => {
// console.log(result)
// }).catch((error) => {
// console.log(error) // 打开的是 'success'
// })

  • 手写Promise api

Async、await

await可以看成是Promise的语法糖(实际上是Generate的语法糖),效果和Promise的回调地狱一样,只是代码看起来好看点。

测试代码
/**
 * async await
 */

// async function fn () {
// // return await 123
// // 等同于
// return 123
// }
// fn().then(res => console.log(res))
// console.log(fn)

// async function async1() {
// console.log("async1 start");
// await async2();
// console.log("async1 end");
// }
// async function async2() {
// console.log("async2");
// }
// async1();
// console.log('start')

// async function async1() {
// console.log("async1 start");
// await async2(); // 紧跟着 await 后面的语句相当于放到了 new Promise 中,下一行及之后的语句相当于放在 Promise.then 中
// console.log("async1 end");
// }
// async function async2() {
// setTimeout(() => {
// console.log('timer')
// }, 0)
// console.log("async2");
// }
// async1();
// console.log("start"

// async function async1() {
// console.log("async1 start");
// await async2();
// console.log("async1 end");
// setTimeout(() => {
// console.log('timer1')
// }, 0)
// }

// async function async2() {
// setTimeout(() => {
// console.log('timer2')
// }, 0)
// console.log("async2");
// }

// async1();

// setTimeout(() => {
// console.log('timer3')
// }, 0)

// console.log("start")

综合

async function a1() {
  console.log('a1 start')
  await a2()
  console.log('a1 end')
}
async function a2() {
  console.log('a2')
}

console.log('script start')

setTimeout(() => {
console.log('setTimeout')
}, 0)

Promise.resolve().then(() => {
console.log('promise1')
})

a1()

let promise2 = new Promise(resolve => {
resolve('promise2.then')
console.log('promise2')
})

promise2.then(res => {
console.log(res)
Promise.resolve().then(() => {
console.log('promise3')
})
})
console.log('script end')

/\*_ 第一次做错的结果
script start
a1 start
a2
promise1
a1 end
promise2
script end
promise2.then
promise3
setTimeout
_/

/\*_ 正确结果
script start
a1 start
a2
promise2
script end
promise1
a1 end
promise2.then
promise3
setTimeout
_/

参考

评论区

Twikoo giscus