封装Promise版本的 readFile

写在前面

做者最近遇到了一个有趣的问题,咱们都知道文件读取有两种类型javascript

fs.readFileSync(); //同步读取
fs.readFile(); //异步读取
复制代码

而Promise 是异步编程的一种解决方案, 那么咱们可否封装一个Promise版本的 readFile呢?css

引子

咱们来看看阮一峰老师关于javascript是单线程的解释html

连接:www.ruanyifeng.com/blog/2014/1…java

JavaScript语言的一大特色就是单线程,也就是说,同一个时间只能作一件事,在发出一个调用时,必须等待上一个任务执行完才能执行下一个任务,这种执行模式叫作同步。单线程就意味着,全部任务须要排队,前一个任务结束,才会执行后一个任务。若是前一个任务耗时很长,后一个任务就不得不一直等着。JavaScript语言的设计者意识到,这时主线程彻底能够无论IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回告终果,再回过头,把挂起的任务继续执行下去。因而,全部任务能够分红两种,一种是同步任务,另外一种是异步任务。编程

什么是同步编程?

所谓同步编程,就是计算机按顺序一行一行依次执行代码,当前代码任务耗时执行会阻塞后续代码的执行。promise

什么是异步编程?

所谓异步编程,就是在调用在发出后,这个调用就直接返回了,调用者不会当即获得结果,可是不会阻塞,能够继续执行后续的操做。用一句话来讲就是并发

程序无须按照代码顺序自上而下的执行app

须要的文件

这是咱们要引入的template.html文件koa

<html>
    <head></head>
    <link rel="stylesheet" href="style.css">
    <body>
        <h1>不吃算拉~</h1>
        <img src="./eat.jpg" alt="" width="100px" height="100px">
        <script src="./common.js"></script>
    </body>
</html>
复制代码

样式和js能够本身写,我写的有点粗糙,在本地上预览效果以下:异步

同步方式读取

如今咱们用同步的方式读取这个文件

const Koa = require('koa'); 
const app = new Koa(); 
const static = require('koa-static');
const fs = require('fs');
const main = ctx => {
    ctx.response.type = 'html'; // 响应头
    const html = fs.readFileSync('./template.html','utf-8');    // 同步读取
    // console.log(html);
    ctx.response.body =html;
}
app.use(static('./'));
app.use(main); 
app.listen(3000);
复制代码

这是同步的写法,会形成阻塞。对于高并发来讲,很是消耗时间。

异步方式读取

如今咱们来使用性能更高,速度更快,并且没有阻塞的异步方法。 代码以下:

const Koa = require('koa'); 
const app = new Koa(); 
const static = require('koa-static');
const fs = require('fs');
const main = async ctx => {
    ctx.response.type = 'html'; // 响应头
    // 封装Promise 版本的 readFile
    let pReadFile = function (filePath) {
        return new Promise(function (resolve, reject) {
            fs.readFile(filePath, 'utf-8', function (err, data) {
                if (err) {
                    reject(err);
                }
                resolve(data);
            });
        })
    }
    await pReadFile('./template.html').then(data => {
        ctx.response.body = data;
    })
}
app.use(static('./'));
app.use(main); // 启用了一个服务 给访问者用 Visitors 使用
app.listen(3000);
复制代码

预览效果

能够看到,咱们成功完成了readFile中Promise版本的封装。

对上述代码的一些解释

  • 引入了koa-static 处理静态资源
  • Promise,promise是ES6为解决异步回调而生,它经过 then 链来解决多层回调的问题,我又结合了 async/await 来进一步优化它。
  • 什么是Async/Await?
    • async/await是基于Promise实现的,它不能用于普通的回调函数。
    • async/await与Promise同样,是非阻塞的。
    • async 是“异步”的简写,而 await 能够认为是 async wait 的简写。因此应该很好理解 async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。

总结

对于以上代码,其实咱们还有更简单的方法来实现,这里用到了流(Stream)的思想

const fs = require('fs');
const Koa = require('koa');
const app = new Koa();
const static = require('koa-static');
const main = ctx =>{
    ctx.response.type = 'html';
    ctx.response.body = fs.createReadStream('./template.html');
}
app.use(static('./'));
app.use(main);
app.listen(3000,function(){
    console.log('在3000端口上启动成功')
});
复制代码

能够看到, 流的使用更增强大。这里不作过多赘述。

写在后面

笔者目前仍是一名在读大三学生, 若是有相应错误,欢迎大佬指正,也欢迎你们可以一块儿交流问题,但愿能和你们一块儿获得成长!

相关文章
相关标签/搜索