前端学习手册-Promise

同步异步的区别

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

  1. 同步:会阻塞后面代码执行
  2. 异步:不会阻塞后面代码执行,如:定时任务、网络请求

Promise:解决了,回调地狱的问题

手写Promise加载两张图片

const url1 = '111.jpg';
const url2 = '222.jpg';


loadImg(url1).then(img =>{
    console.log(img.width)
    return img
}).then(img =>{
    console.log(img.height)
    return loadImg(url2)
}).then(img2 =>{
    console.log(img2.height)
    return img2
}).then(img2 =>{
    console.log(img2.width)
})

JS 的特色就是异步编程,所有有很多关于异步的考点,本章都会讲解。如 event loop、promise、async-await、微任务和宏任务。学不会这些,就不算是精通 JS ,也无法进大厂。

产出

  1. 全面使用 Promise
  2. 学会 async await 语法
  3. 学会 event loop 流程
  4. 认识微任务和宏任务

主要内容

  1. event loop 执行过程
    事件循环/事件轮询
    event loop 是异步回调的实现原理
    Js执行:
    从前到后,一行一行执行
    如果某一行报错,则停止下面的代码执行
    先把同步代码执行完,在执行异步
  2. Promise 全面使用
  3. async await 全面使用:是同步语法,彻底消灭回调函数
    async/await 是消灭异步回调的中级武器,但和promise并不互斥
    async执行,返回的是promise对象
    await 相当于promise的then
    try…catch 可以捕获异常 代替了promise的catch

async/await

  • 语法介绍
  • 和 Promise 的关系
  • 异步本质
  • for…of

有很多 async 的面试题,例如

  • async 直接返回,是什么
  • async 直接返回 promise
  • await 后面不加 promise
  • 等等,需要找出一个规律

语法介绍

用同步的方式,编写异步。

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

async function loadImg1() {
    const src1 = 'http://www.imooc.com/static/img/index/logo_new.png'
    const img1 = await loadImg(src1)
    return img1
}

async function loadImg2() {
    const src2 = 'https://avatars3.githubusercontent.com/u/9583120'
    const img2 = await loadImg(src2)
    return img2
}

(async function () {
    // 注意:await 必须放在 async 函数中,否则会报错
    try {
        // 加载第一张图片
        const img1 = await loadImg1()
        console.log(img1)
        // 加载第二张图片
        const img2 = await loadImg2()
        console.log(img2)
    } catch (ex) {
        console.error(ex)
    }
})()

和 Promise 的关系

  • async 函数返回结果都是 Promise 对象(如果函数内没返回 Promise ,则自动封装一下)
async function fn2() {
    return new Promise(() => {})
}
console.log( fn2() )

async function fn1() {
    return 100
}
console.log( fn1() ) // 相当于 Promise.resolve(100)
  • await 后面跟 Promise 对象:会阻断后续代码,等待状态变为 resolved ,才获取结果并继续执行
  • await 后续跟非 Promise 对象:会直接返回
(async function () {
    const p1 = new Promise(() => {})
    await p1
    console.log('p1') // 不会执行
})()

(async function () {
    const p2 = Promise.resolve(100)
    const res = await p2
    console.log(res) // 100
})()

(async function () {
    const res = await 100
    console.log(res) // 100
})()

(async function () {
    const p3 = Promise.reject('some err')
    const res = await p3
    console.log(res) // 不会执行
})()
  • try…catch 捕获 rejected 状态
(async function () {
    const p4 = Promise.reject('some err')
    try {
        const res = await p4
        console.log(res)
    } catch (ex) {
        console.error(ex)
    }
})()

总结来看:

  • async 封装 Promise
  • await 处理 Promise 成功
  • try…catch 处理 Promise 失败

异步本质

await 是同步写法,但本质还是异步调用。

async function async1 () {
  console.log('async1 start')
  await async2()
  console.log('async1 end') // 关键在这一步,它相当于放在 callback 中,最后执行
}

async function async2 () {
  console.log('async2')
}

console.log('script start')
async1()
console.log('script end')

即,只要遇到了 await ,后面的代码都相当于放在 callback 里。

for…of

// 定时算乘法
function multi(num) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(num * num)
        }, 1000)
    })
}

// // 使用 forEach ,是 1s 之后打印出所有结果,即 3 个值是一起被计算出来的
// function test1 () {
//     const nums = [1, 2, 3];
//     nums.forEach(async x => {
//         const res = await multi(x);
//         console.log(res);
//     })
// }
// test1();

// 使用 for...of ,可以让计算挨个串行执行
async function test2 () {
    const nums = [1, 2, 3];
    for (let x of nums) {
        // 在 for...of 循环体的内部,遇到 await 会挨个串行计算
        const res = await multi(x)
        console.log(res)
    }
}
test2()
  1. 微任务和宏任务

面试题

异步 题目

  • 描述 event loop 运行机制(可画图)
  • Promise 哪几种状态,如何变化?
  • 宏任务和微任务的区别
  • 场景题:Promise catch 连接 then
  • 场景题:Promise 和 setTimeout 顺序
  • 场景题:各类异步执行顺序问题

Promise catch 连接 then

// 第一题
Promise.resolve().then(() => {
    console.log(1)
}).catch(() => {
    console.log(2)
}).then(() => {
    console.log(3)
})
// 1 3

// 第二题
Promise.resolve().then(() => {
    console.log(1)
    throw new Error('erro1')
}).catch(() => {
    console.log(2)
}).then(() => {
    console.log(3)
})
// 1 2 3

// 第三题
Promise.resolve().then(() => {
    console.log(1)
    throw new Error('erro1')
}).catch(() => {
    console.log(2)
}).catch(() => { // 注意这里是 catch
    console.log(3)
})
// 1 2

async/await 语法问题

async function fn() {
    return 100
}
(async function () {
    const a = fn() // ??               // promise
    const b = await fn() // ??         // 100
})()
(async function () {
    console.log('start')
    const a = await 100
    console.log('a', a)
    const b = await Promise.resolve(200)
    console.log('b', b)
    const c = await Promise.reject(300)
    console.log('c', c)
    console.log('end')
})() // 执行完毕,打印出那些内容?

Promise 和 setTimeout 顺序

console.log(100)
setTimeout(() => {
    console.log(200)
})
Promise.resolve().then(() => {
    console.log(300)
})
console.log(400)
// 100 400 300 200

执行顺序问题

网上很经典的面试题

async function async1 () {
  console.log('async1 start')
  await async2() // 这一句会同步执行,返回 Promise ,其中的 `console.log('async2')` 也会同步执行
  console.log('async1 end') // 上面有 await ,下面就变成了“异步”,类似 cakkback 的功能(微任务)
}

async function async2 () {
  console.log('async2')
}

console.log('script start')

setTimeout(function () { // 异步,宏任务
  console.log('setTimeout')
}, 0)

async1()

new Promise (function (resolve) { // 返回 Promise 之后,即同步执行完成,then 是异步代码
  console.log('promise1') // Promise 的函数体会立刻执行
  resolve()
}).then (function () { // 异步,微任务
  console.log('promise2')
})

console.log('script end')

// 同步代码执行完之后,屡一下现有的异步未执行的,按照顺序
// 1. async1 函数中 await 后面的内容 —— 微任务
// 2. setTimeout —— 宏任务
// 3. then —— 微任务
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值