JS异步模型、Promise

452 阅读2分钟

1. JS运行机制

  • 先说结论:JS是完全单线程的异步模型。同步在前,异步在后,所有异步任务都要等待当前同步执行完。
  • 先来说说提到的几个概念:

进程:是CPU的执行单位。对于单核处理器,通过分配时间片的方式,让一个任务执行一段时间,再切换到另外一个任务运行一段时间。不同任务交替往复一直执行。上述过程就是进程(也叫做线程的上下文切换),浏览器可以简单理解为一个进程。每个Tab页即为一个线程,JS代码占用一个线程。

同步:一种阻塞式编程模型,前一个任务执行完成之后,才能进行下一个任务,无并发和并行的概念。

异步:一种非阻塞式编程模型,不同任务之间并不会相互等待,典型实现异步的方式是通过多线程编程,多核环境下,每个线程分配到独立的核心上运行,实现真正的并行。还有一种是单线程并发

JS通过回调函数机制做到单线程并发,比如通过fetch()函数同时访问多个网络资源,调用fetch()函数时,程序不会等待而是继续执行下去,主程序和回调函数运行在同一线程中,这种方式来做到单线程并发。

2. JS线程组成

浏览器中一个Tab页面的实际线程组成,多线程切换:

  • GUI渲染线程(屏幕刷新)
  • JS引擎线程
  • 事件触发线程
  • 定时器触发线程
  • HTTP请求线程

3. JS运行模型

image.gif

4. 处理异步

4.1 传统的回调函数

setTimeout(),但是依次执行多个回调操作,就会出现嵌套过多,出现回调地狱问题。

setTimeout(()=>{
    console.log("hello");
},3000);
    console.log("see you again");
// 先打印出see you again,3s后执行hello   

4.2 用Promise来解决回调地狱。

  • AJAX技术

JS中使用Promise的API fetch用来发起一个请求来获取服务器数据,用它动态更新页面的内容

fetch('https://jsonplaceholder.typicode.com/posts/1')

Promise{}
  • 调用then方法:
fetch('https://jsonplaceholder.typicode.com/posts/1')
    .then((response) => response.json())

如果请求在未来成功完成,回调函数会被调起,请求的结果会以参数的形式传递进来

  • 链式调用:

链式结构把多个异步操作串联起来

fetch('https://jsonplaceholder.typicode.com/posts/1')
    .then((response) => response.json())
    .then((json) => console.log(json))
  • 捕获错误:
fetch('https://jsonplaceholder.typicode.com/posts/1')
    .then((response) => response.json())
    .then((json) => console.log(json))
    .catch((error)=> console.log(error))

4.3 async / await 关键字(基于Promise之上的语法糖)

Javascript ECMA17 新标准

使用async关键字将函数标记为异步函数(返回值为Promise对象的函数):

async function f(){
    // await 取代 then ,等待Promise完成后直接返回最终的结果
    await fetch("http://...")  
}
f();

4.4 Promise API

  • Promise.all
async function f(){
    const a = await fetch();
    const b = await fetch();
}
async function f(){
    const promiseA = fetch();
    const promiseB = fetch();
    
    const [a, b] = await Promise.all([promiseA, promiseB])
}