3 迅速搞定js js异步(SY)

目录

 1 单线程、异步、同步

2 callback hell(回调地狱)

3 Promise

4  基础知识回顾

5 event loop(事件循环)

6  promise进阶

7 async/await

8 宏任务/微任务

9 请描述event loop(事件循环/事件轮询)的机制,可画图

问答题:请描述event loop(事件循环/事件轮询)的机制,可画图

​编辑什么是宏任务、微任务,两者有什么区别

​编辑Promise有哪三种状态,如何变化

场景题:promise then和catch的连接(常考且实用)​编辑async/await语法​编辑

promise和setTimeout的顺序(常考)

​编辑外加async/await的顺序问题(好题,综合深入)

手写priomise


 1 单线程、异步、同步

单线程:

  • JS是单线程语言,只能同时做一件事儿

  • 浏览器和nodejs已支持JS启动进程,如Web Worker

  • JS和DOM渲染共用同一个进程,因为JS可修改DOM结构

异步:

  • 背景:基本js单线程的背景产生,并不是为了异步而异步

  • 目的:遇到等待(网络请求,定时任务)不能卡住,使得下面的代码继续执行

  • 实现:基于callback函数形式调用

  • 原理:event loop 就是异步回调的实现原理

同步:

  • 从上到下依次执行代码

  • 遇到等待(网络请求,定时任务)会卡住,使得下面的代码不执行

异步与同步:

  • 基于js是单线程

  • 异步不会阻塞代码执行

  • 同步会阻塞代码执行

    //异步 callback回调函数
    console.log(100)
    setTimeout(() => {
        console.log(200)
    }, 1000)
    console.log(300)
    
    // 同步
    console.log(100)
    alert(200)
    console.log(300)

2 callback hell(回调地狱)

3 Promise

解决回调地狱,把多层嵌套改成了管道串联的形式,提高代码可读性

1.主要是用来解决回调地狱的问题 
2.所以出现了promise 
3.现在主流的方法是使用async 和 await 来进行解决异步问题。 
4.async 和 await 本质上是一个语法糖 使函数的返回值包含在promise中返回。
resolve 触发 then,then中的函数接收resolve 的参数
reject 触发 catch,catch中的函数接收reject 的参数

        

 手写Promise加载一张图片

const url = "" // (img url)

function loadImg (src) {
    return new Promise(
        (resolve, reject) => {
            const img = document.createElement('img')
            img.onload = () => {
                resolve(img)
            }
            img.onerror = () => {
                reject(new Error('图片加载失败'))
            }
            img.src = src
        }
    )
}

loadimg(url).then((img) => {
    console.log(img.width)
    return img
}).then(img => {
    console.log(img.height)
}).catch(ex => console.log(ex)

4  基础知识回顾

 
  • 变量类型与计算

  1. typeof判断类型:number string boolean symbol function undefined object,但是对于object不能细分(无法区分是object还是array或者null)

  2. === 和 == 的区别: === 为全等,不存在隐式转换, == 为相等,存在隐式转换(例如'' == 0 为true),通常都用严格全等===,除了极少情况用==(例如obj.a == null)

  3. 值类型、引用类型区别:值类型存储在栈中,引用类型存储在堆中

  4. 手写深拷贝

function deepClone(target){
    if(typeof target !== 'object' || target === null) return target
    let newObj = target instance Array ? [] : {}
    for(let key in target){
        if(target.hasOwnProperty(key)){
            let newObj[key] = deepClone(target[key])
        }
    }
    return newObj
}

 5. truly和falsely变量 (a =100,那么!!a = true)

  •  原型和原型链

  1. 如何判断一个变量是不是数组: xxx instanceof Array

  2.  class本质:原型链 + 子类调用父类构造函数

  3. 原型与原型链的图示:暂无

6 作用域与闭包

  1. this不同场景如何取值:非严格模式下,函数默认指向window,如果使用xxx.fn(),那么this指向调用它的对象;箭头函数没有自己的this,使用的是它父级作用域的this

  2. 实际开发中闭包的作用:将数据封装起来,并向外暴露调用它的相关api,实现数据的私有化

function createCache(){
    const data {}
    return {
        get(key){
            return data[key]
        }
        set(key,val){
            data[key] = val
        }
    }
}

let data = createCache(){}
data.set('a', 50)
data.get('a')   // 50

   3.手写bind

Function.prototype.bind1 = function(){
    const args = Array.of(...arguments)
    const _this = args.shift()
    const self = this
    return function(){
        return self.apply(_this,args)
    }
}

5 event loop(事件循环)

 

event loop(事件循环/事件轮询)机制

    js是单线程运行的

    异步要基于回调来实现

    event loop 就是异步回调的实现原理

js如何执行

    从前往后,一行一行执行

    如果某一行执行报错,则停止下面代码的执行

    先把同步代码执行完,再执行异步

 

event loop

执行图解:

  • Call Stack:调用栈(同步任务队列)

  • Web APIs:浏览器运行环境对自己Api的一些定义,如:定时器,Dom事件...(宏任务队列)

  • Event Loop:事件循环/轮询机制

  • Callback Queue:回调函数队列

执行总结:

  1. 同步代码,一行一行放在Call Stack执行

  2. 遇到异步,会先“记录”下,等待时机(定时、网络请求等)

  3. 时机到了,就移动到Callback Queue

  4. 如Call Stack为空(即同步代码执行完),先尝试DOM渲染后,Event Loop再开始工作

  5. 轮询查找Callback Queue,如有则移动到Call Stack执行

  6. 然后继续轮询查找(永动机一样)

6  promise进阶

promise 有三种状态,分别是:pending(初始化状态)、resolved(成功状态)、rejected(失败状态)

pending是当用户创建了promise对象时的状态,即new Promise( resolved , rejected ){ } 

此时后面两个都未被调用,所以为初始化pending。该状态下,不能触发then和catch

resolved是当用户触发后的成功状态,该状态下,只能触发then的回调函数,不能触发catch 

rejected是当用户触发后的失败状态,该状态下,只能触发catch的回调函数,不能触发then

 

    三种状态:

        pending(等待结果)resolved(已成功) rejected(已失败)

        pending -> resolved 或 pending -> rejected

         变化不可逆

 

   状态的表现和变化:

        pending状态,不会触发 then 和 catch

        resolved状态,会触发后续的 then 回调函数

        rejected状态,会触发后续的 catch 回调函数

    then 和 catch 对状态的影响

  • then 正常返回resolve状态的promise,如果有报错,返回的是reject

  • catch正常返回resolve状态的promise,如果有保持,返回的是reject

3 resolve会触发then的回调, reject会触发catch的回调

7 async/await

  • 解决异步回调callback hell(回调地狱)
  • Promise then catch 链式调用,但也是基于回调函数
  • async/await(同步语法编写异步代码)
  • 是同步语法,彻底消灭回调函数

匿名函数前面经常会加 ! ,用来区分和前面的代码

 await后面,可以是Promise,也可以是async函数;

 

async:        

  • 返回的是一个 Promise 对象

  • 若返回值不是 Promise 对象,则相当于返回 Promise.resolve(xxx)

await:

  • 只能在 async 函数中使用

  • await 相当于 Promise 的 then

  • 所以 await 后面是一个 Promise 对象,若不是,则相当于 Promise.resolve(xxx)

  • 且 await 下面的代码,相当于放在一个callback回调中,即异步,且属于微任务

  • 若 await 后面的是一个 rejected 状态的 Promise 对象,则 await 下面的代码不会执行

async/await 和 Promise 关系?

◆执行async函数,返回的是Promise对象 

◆await 相当于Promise的then

◆try..catch 可捕获异常, 代替了Promise的catch

◆async/await 只是一个语法糖,但这颗糖真香!

8 宏任务/微任务

ES6 规范中,microtask 称为 jobs,macrotask 称为 task
宏任务是由宿主发起的,而微任务由JavaScript自身发起。

macro Task     vs  micro Task 

 js 是单线程,且和 DOM 渲染共用同一个线程,因为js执行过程中,需要留一些时间给 DOM 完成渲染

call stack空闲的时候,
 1 event loop
 2 进行dom渲染
3 将call Queue队列里的回调函数添加到call stack里执行
1 event loop
回到第一步

宏任务dom渲染后触发 浏览器规定 放在callbackqueue 

微任务dom渲染前触发  Es6语法规定 放在 micro task queue

所以微任务触发早于宏任务

 微任务在DOM渲染之前触发,宏任务在DOM渲染之后触发,参考代码

所以真实的执行Event loop

1、call stack
2、微任务(存于微任务队列)
3、DOM渲染
4、触发Event loop(宏任务在这)

总结 

 

9 请描述event loop(事件循环/事件轮询)的机制,可画图

event loop(事件循环/事件轮询)
1. JS 是单线程运行的
2. 异步要基于回调来实现
3. event loop 就是异步回调的实现机制

event loop执行图解:

  • Call Stack:调用栈(同步任务队列)

  • Web APIs:浏览器运行环境对自己Api的一些定义,如:定时器,Dom事件...(宏任务队列)

  • Event Loop:事件循环/轮询机制

  • Callback Queue:回调函数队列

同步代码,一行一行放在CallStack执行

遇到异步,会先“记录”下,等待时机(定时、网络请求等)

时机到了,就移动到Callback Queue

如Call Stack为空(即同步代码执行完)Event Loop开始工作

轮询查找Callback Queue,如有则移动到Call Stack执行

然后继续轮询查找(永动机一样)

JS 如何执行?

  • 从前到后,一行一行执行

  • 如果某一行执行报错,则停止下面代码执行

  • 先把同步代码执行完,在执行异步

总结 event loop 执行过程 

  • 同步代码,一行一行放在 Call Stack 执行

  • 遇到异步,会先“记录”下,等待时机(定时,网络请求等)

  • 时机到了,就会移动到 Callback Queue

  • 如果  Call Stack 为空(即异步代码执行完)Event loop 开始工作

  • 轮训查找 Callback Queue,如有则移动到  Call Stack 执行

  • 然后继续轮询查找(永动机一样)

DOM 事件和 event loop 的关系

  • JS 是单线程的

  • 异步(setTimeout,Ajax 等)使用回调,基宇 event loop

  • DOM 事件也使用回调,基宇 event loop

DOM渲染和Event Loop:

  • Call Stack为空时,都会先尝试DOM渲染,再触发Event Loop

问答题:
请描述event loop(事件循环/事件轮询)的机制,可画图


什么是宏任务、微任务,两者有什么区别


Promise有哪三种状态,如何变化

 

场景题:
promise then和catch的连接(常考且实用)
async/await语法

 a = 100  b= 一个 promise 


promise和setTimeout的顺序(常考)


外加async/await的顺序问题(好题,综合深入)

 

手写priomise

 ​​​​​​

const PENDING ='pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise{
    state = PENDING
    value = null
    reason = null
    
    onFulfilledCallbacks = [] // 记录成功的回调
    onRejectedCallbacks = [] // 记录失败的回调
    constructor(executor){
        try{
            executor(this.resolveHandler,this.rejectHandler)        
        }catch(err){
            this.rejectHandler(err)
        }

    }
    
    resolveHandler = (value) => {
        if(this.state === PENDING){
            this.state = FULFILLED
            this.value = value
            while(true){
                this.onFulfilledCallbacks.shift()(this.value)
            }
        }
    }
    
    rejectHandler = (reason) => {
        if(this.state === PENDING){
            this.state = REJECTED
            this.reason = reason
            while(true){
                this.onRejectedCallbacks.shift()(this.value)
            }
        }
    }
    
    then(onFulfilled, onRejected){
        const realOnfulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
        const realOnRejected = typeof onRejected === 'function ? onRejected : reason => reason
        
        const promise = new MyPromise((resolve, reject)=>{
            if(this.state === FULFILLED){
                try{
                    const newValue = realOnfulfilled(this.value)
                    resolvePromise(newValue, resolve, reject)                
                }catch(err){
                    reject(err)
                }

            }else if(this.state === REJECTED){
                try{
                    const newReason = realOnRejected(this.value)           
                }catch(err){
                    reject(err)
                }

            }else if(this.state === PENDING){
                this.onFulfilledCallbacks.push(realOnFulfilled)
                this.onRejectedCallbacks.push(realOnRejected)
            }
        })
        return promise
    }
}

function resolvePromise(newValue, resolve, reject ){
    // 判断产生的Promise是否为Promise本身
    if(newValue instanceOf MyPromise){
        newValue.then(resolve, reject)
    }else{
        resolve(newValue)
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值