如何优雅的实现回调函数?

1,070 阅读2分钟

「我正在参与掘金会员专属活动-源码共读第一期,点击参与

本篇文章又是一期优雅的代码编程介绍———回调函数。

传统的nodejs编程都是这样的

const fs = require('fs')
fs.readFile('test.txt','utf8', function(err, dataStr){
    if(err){}
})

嵌套层级如果多了就成回调地狱了。如果我们将这种风格的代码转换成这样呢?

const fs = require('fs');
const {promisfy, waitFor, promisfyNoError} = require('promisfy');
const readFile = promisfy(fs.readFile);
let content = await readFile('myfile.txt', {encoding:'utf8'});
return content;
http.createServer(80, function(req, res) {
    async function handleRequest(req, res) {
        if (req.method === 'POST') {
            req.body = await waitFor(req.sock, 'data');
        }
    }
})

这种promisfy的风格是不是简洁优雅,一行就搞定了。

安装

npm install --save promisfy

promisfy包里封装了以下三个函数

  • promisfy: 处理fs这种回调API
  • waitFor: 处理监听事件和流的,对象具有xx.on('event'),xx.on('data'),xx.on('end')这些监听事件。
  • promisfyNoError: 处理回调没有错误抛出的API

源码

  • 参数:传入需要promisfy的函数和上下文
  • 返回值:返回一个新函数
const readFile = promisfy(fs.readFile);
let content = await readFile('myfile.txt', {encoding:'utf8'});

解析代码

  1. 通过agruments内置对象取到函数readFile的参数。
  2. 调用readFile返回的是一个Promise对象。
  3. Promise里声明了一个callback函数。callback传入的参数结构是第一个为err对象,剩余参数为成功的结果。err对象通过reject函数处理,剩余参数用resolve函数处理。
  4. 处理函数的参数fnArgs,argscallback
  5. 最后调用这个函数并传入上下文。
  • promisfyNoError:和上述逻辑一样除去了err对象的部分;
  • waitFor:对普通事件监听和流处理做的promisfy封装;

结束语

对于回调这种风格的函数还有事件监听和数据流进行promisfy处理后,就节省了很多很多代码行数,清晰明了。优雅的风格依然还在,还能做一个艺术工程师。

类似的,我们在微信网页开发的时候使用weixin-jssdk,也可以自己封装一个promisfy风格的函数。我们的代码里也不会有看着费劲的屎山了。

wx.request({
    xxx:'',
    xxx:'',
    xxx:'',
    success(){},
    fail(){}
})