上节课我们讲解了 nodejs 处理 http 请求,今天我们讲下 callback, promise 和 async, await

callback

js 代码处理逻辑都是异步,会造成 callback 层层嵌套。简称:回调地狱,非常不好维护,我们举例说明下 我们在 sir-node 中新建个目录 callback-test, 里面新建个 callback.js

1
2
$ mkdir callback-test && cd callback-test/
$ touch callback.js

callback.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const fs = require('fs')
const path  = require('path')
//callback 方式获取文件内容
function getFile(fileName,callback){
    const fullName = path.resolve(__dirname,"",fileName)
    fs.readFile(fullName,(err,data)=>{
        if(err){
            console.error(err)
            return
        }
        callback(JSON.parse(data.toString()))
    })
}
// 测试
getFile('a.json',aData=>{
    console.log('aData',aData)
    getFile(aData.next,bData=>{
        console.log('bData',bData)
        getFile(bData.next,cData=>{
            console.log('cData',cData)
        })
    })
})

再新建 3 个文件 a.json, b.json, c.json,内容如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// a.json

{"next":"b.json"}

// b.json

{"next":"c.json"}

// c.json

{"next":"test"}
1
2
3
4
$ node callback.js
aData { next: 'b.json' }
bData { next: 'c.json' }
cData { next: 'test' }

由此可见,callback 层层嵌套。当然现在只有 3 层,实际项目中可能会有很多层,可想而知维护的难度,接下来就是解决方案。

promise

新建个 promise.js 文件,代码如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const fs = require('fs')
const path  = require('path')
//promise 方式获取文件内容
function getFile(fileName){
    const promise = new Promise((resolve,reject)=>{
        const fullName = path.resolve(__dirname,"",fileName)
        fs.readFile(fullName,(err,data)=>{
            if(err){
                reject(err)
                return
            }
            resolve(JSON.parse(data.toString()))
        })
    })
    return promise
}
// 测试
getFile('a.json').then(aData=>{
    console.log('aData',aData)
    return getFile(aData.next)
}).then(bData=>{
    console.log('bData',bData)
    return getFile(bData.next)
}).then(cData=>{
    console.log('cData',cData)
})

表面看上去代码略微繁琐,但是使用起来很简洁,promise 把 callback 层层嵌套的方式变成了很多个 then 平铺,当然 promise 无法解决把异步代码写成同步的风格,我们来讲下异步写法的终极解决方案,async 和 await

async 和 await

新建个 async.js 文件,代码如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const fs = require('fs')
const path  = require('path')
//promise 方式获取文件内容
function getFile(fileName){
    const promise = new Promise((resolve,reject)=>{
        const fullName = path.resolve(__dirname,"",fileName)
        fs.readFile(fullName,(err,data)=>{
            if(err){
                reject(err)
                return
            }
            resolve(JSON.parse(data.toString()))
        })
    })
    return promise
}
// 测试
async function getFileContent(){
    aData = await getFile('a.json')
    console.log('aData',aData)
    bData = await getFile(aData.next)
    console.log('bData',bData)
    cData = await getFile(bData.next)
    console.log('cData',cData)
}
getFileContent()

async 和 await 也是基于 promise 的,代码写法和同步一样了。

总结

今天我们讲了 callback, promise 和 async, await。你掌握了吗?在项目中我们使用的 koa2 框架完全支持 async 和 await。 有问题欢迎到群里和志同道合的小伙伴一起交流。 下节课我们介绍项目功能和技术架构,继续加油吧,Let’s go!