Skip to content

异步编程

一、Callback

Callback是传统的一种异步解决方案

通过在执行异步的时候,传入一个callback,等到异步执行返回结果之后,在调用callback

例子:

js
const fs = require('fs')

function ajax(url,callback){
    try {
        const res = fs.readFile(url,'utf-8',callback)
    } catch (err){
        callback(new Error(err))
    }
}

const callback = function (err,res){
    console.log(res)
    ajax('./posts.json',(err,res) => {
        console.log(res)
    })
}
ajax('./user.json',callback)
const fs = require('fs')

function ajax(url,callback){
    try {
        const res = fs.readFile(url,'utf-8',callback)
    } catch (err){
        callback(new Error(err))
    }
}

const callback = function (err,res){
    console.log(res)
    ajax('./posts.json',(err,res) => {
        console.log(res)
    })
}
ajax('./user.json',callback)

缺点:

当请求之间存在依赖的时候,callback层级过深,会产生回调地狱

二、Promise

Promise是ES6新增的一个异步解决方案

Promise是一个构造函数,接受一个函数并且同步调用。其内部维护了一个状态,初始化是为等待状态,在调用传入的函数时,其向函数注入两个函数,第一个可以将状态更改为成功状态,第二个更改为失败状态 。Promise会根据状态执行对应的回调,其中成功会执行then中的第一个参数,失败会只想then的第二个参数或者catch的参数

例子:

js
const fs = require('fs')

function ajax(url){
    return new Promise((resolve,reject) => {
        try {
            const res = fs.readFileSync(url,'utf-8')
            resolve(res)
        } catch (err){
            reject(new Error(err))
        }
    })
}

ajax('./user.json')
    .then(res => {
        console.log(res)
        return ajax('./posts.json')
    })
    .then(res => {
        console.log(res)
    })
    .catch(err => {
        console.log(err)
    })
const fs = require('fs')

function ajax(url){
    return new Promise((resolve,reject) => {
        try {
            const res = fs.readFileSync(url,'utf-8')
            resolve(res)
        } catch (err){
            reject(new Error(err))
        }
    })
}

ajax('./user.json')
    .then(res => {
        console.log(res)
        return ajax('./posts.json')
    })
    .then(res => {
        console.log(res)
    })
    .catch(err => {
        console.log(err)
    })

优点: 支持链式调用,解决回调地狱的问题

三、Generator

generator(生成器))是ES6标准引入的,是一个特殊的函数,or由function *定义(注意多出的 *号),并且,除了return语句,还可以用yield返回多次。

执行generator函数会返回一个generator对象,并不会执行函数

通过next()方法会执行generator的代码,然后,每次遇到yield x; 就返回一个对象{value: x, done: true/false},然后“暂停”。 返回的value就是yield的返回值,done表示这个generator是否已经执行结束了。 如果done为true,则value就是return的返回值。 当执行到done为true时,这个generator对象就已经全部执行完毕,不要再继续调用next()了。

例子:

js
const fs = require('fs')

function ajax(url){
    return new Promise((resolve,reject) => {
        try {
            const res = fs.readFileSync(url,'utf-8')
            resolve(res)
        } catch (err){
            reject(new Error(err))
        }
    })
}

function *generator(){
    yield ajax('./user.json')//注意:ajax返回的是Promise对象

    yield ajax('./posts.json')
}

const g = generator()

g.next().value.then(res => {
    console.log(res)
    return g.next()
})
.then(res => {
    console.log(res)
})
const fs = require('fs')

function ajax(url){
    return new Promise((resolve,reject) => {
        try {
            const res = fs.readFileSync(url,'utf-8')
            resolve(res)
        } catch (err){
            reject(new Error(err))
        }
    })
}

function *generator(){
    yield ajax('./user.json')//注意:ajax返回的是Promise对象

    yield ajax('./posts.json')
}

const g = generator()

g.next().value.then(res => {
    console.log(res)
    return g.next()
})
.then(res => {
    console.log(res)
})

四、a、Async/Await

async 是一个修饰符,async 定义的函数会默认的返回一个Promise对象resolve的值, 因此对async函数可以直接进行then操作,返回的值即为then方法的传入函数

wait 关键字 只能放在 async 函数内部, await关键字的作用 就是获取 Promise中返回的内容, 获取的是Promise函数中resolve或者reject的值

例子:

js
const fs = require('fs')

async function ajax(url){
    return new Promise((resolve,reject) => {
        try {
            fs.readFile(url,'utf-8',
                (err,res) => {
                    if(err) reject(err)

                    resolve(res)
                }
            )
        } catch (err){
            reject(new Error(err))
        }
    })
}

async function getData(){
    const users = await ajax('./user.json')
    console.log(users)
    const posts = await ajax('./posts.json').then(res => res)
    console.log(posts)
}

getData()
const fs = require('fs')

async function ajax(url){
    return new Promise((resolve,reject) => {
        try {
            fs.readFile(url,'utf-8',
                (err,res) => {
                    if(err) reject(err)

                    resolve(res)
                }
            )
        } catch (err){
            reject(new Error(err))
        }
    })
}

async function getData(){
    const users = await ajax('./user.json')
    console.log(users)
    const posts = await ajax('./posts.json').then(res => res)
    console.log(posts)
}

getData()

await 后面必须是一个Promise对象,也可以是一个对象

这个对象必须有一个then属性方法,该方法接收一个参数resolve函数,该函数类似Promise的该方法接收一个参数resolve方法,它的参数会作为await 的结果

如果不执行resolve函数,代码执行将会阻塞

js
(async function (){
    console.log('start')

    async function fn(){
        const res = await {
            then:(r) =>{
                console.log('???')
                r(1)
            }
        }
        console.log('res',res)
    }
    await fn()

    console.log('end')
})()
// start
// ???
// 1
// end
(async function (){
    console.log('start')

    async function fn(){
        const res = await {
            then:(r) =>{
                console.log('???')
                r(1)
            }
        }
        console.log('res',res)
    }
    await fn()

    console.log('end')
})()
// start
// ???
// 1
// end