1. 我是皮皮虾首页
  2. 编程开发
  3. 前端

前端学习记录之二:异步编程

ps:只是针对看的某个课程做的一个简短笔记,方便后续自身复习,有时候逻辑或者板书并不是那么清晰,知识面可能也不全。有合适的机会后面会根据自己看的书籍、资料等完善和补充完善细节。

概述

本节概要

1.同步模式与异步模式

2.时间循环与消息队列

3.异步编程的几种方式

4.Promise异步方案、宏任务/微任务队列

5.Generator异步方案、Async/Await语法糖

单线程JavaScript单线程工作的原因:JS执行环境中负责执行代码的线程只有一个,js代码是运行在浏览器上,主要负责页面动态交互, DOM操作,为避免出现线程同步问题,所以单线程操作。

任务执行模式:同步模式、异步模式

回调函数

回调函数是所有异步编程的方案的根基

回调函数是由调用者定义,交给执行者执行的函数

Promise

解决回调地狱问题

const promise = new Promise((resolve, reject) => {
    // resolve(50)
    reject(new Error('error了喔'))
})
promise.then((data) => {
    console.log(data)
}).catch((e)=>{
    console.log('错误信息', e)
})

promise封装ajax

function ajax(url) {
    return new Promise((resolve, reject)=>{
        var xhr = new XMLHttpRequest()
        xhr.open('get', url)
        xhr.responseType = 'json'
        xhr.onload = ()=>{
            if(this.status === 200) {
                resolve(this.message)
            } else {
                reject(new Error(this.statusText))
            }
        } 
        xhr.send()
    })
}
ajax('/api/test.json').then((value)=>{
    console.log(value)
}, (e)=>{
    console.log('error', e)
})

unhandledRejection 捕获未手动捕获的异常

// 不推荐,应该在代码中明确捕获每一个可能的异常
window.addEventListener('unhandledRejection', e => {})
process.on('unhandledRejection', (reason, promise) => {
    console.log(reason, promise)
    // reason => Promise 失败原因,一般是个错误对象
    // promise => 出现异常的Promise对象
})

promise静态方法

let p = new Promise((resolve, reject)=>{
    resolve(67)
})
let p = Promise.resolve(3)
let p = Promise.reject('reject')
p.then((data)=>{
  console.log(data+4)
}).catch(e=>{
    console.log('error:', e)
})
// 如果传入的是一个对象,并且这个对象也有一个和promise一样的then方法,也能作为promise
// thenable方法。如果需要把第三方的promise对象转换成原生的promise对象可以以这种方式
Promise.resolve({
    then: (onFulfilled, onRejected) =>{
        onFulfilled(3)
    }
})
.then((data)=>{
    console.log(data+3)
})

promise并行执行多个异步任务

all等待所有的任务结束之后结束,返回数组;

race第一个任务结束则结束,返回第一个完成的任务的值;

finally方法用于指定不管Promise对象最后状态如何,都会执行的操作

let p1 = Promise.resolve(1)
let p2 = Promise.resolve(24)
let p3 = Promise.resolve(3535)
let allP =Promise.all([p1, p2, p3])
allP.then((e)=>{
    console.log(e)
})

宏任务和微任务(消息队列和事件循环)

 大部分异步调用的api都是作为宏任务执行的 ,promise的回调会作为微任务执行

微任务是为了提高整体的响应能力 eg:Promise & MutationObserver & process.nextTick

Generator异步方案

增强链式调用的可读性

Generate生成器处理异步任务  ES2015  co库

function * foo () {
    console.log('start')
    const res = yield 'foo'
    console.log(res)
}
const generator = foo()
generator.next()
console.log(generator.next(123))
generator.throw(new Error('error'))

更优异步方案 异步调用更加扁平化

function * foo() {
    console.log('start')
    yield ajax('user.json')
    yield ajax('user2.json')
    // ...
}
const g = foo()
const res = g.next()
console.log(res)

处理逻辑,可使用递归优化

res.value.then((data => {
    const res2 = g.next(data)
    res2.value.then((data) => {
        const res3 = g.next(data)
        // ...
    })
}))

递归优化版本,可复用

function co (generator) {
    const g = generator
    function handleResult (result) {
        if (result.done) return // 生成器函数结束
        result.value.then(data=> {
             handleResult(g.next(data))
        }, error => {
            g.throw(error)
        })
     }
    handleResult(g.next())
}
co(foo)

Async/Await 语法糖  最方便~ 

原创文章,作者:一苇,如若转载,请注明出处:https://wsppx.cn/886/%e7%bd%91%e7%bb%9c%e5%bc%80%e5%8f%91/%e5%89%8d%e7%ab%af/

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注