封裝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端口上啓動成功')
});
複製代碼

能夠看到, 流的使用更增強大。這裏不作過多贅述。

寫在後面

筆者目前仍是一名在讀大三學生, 若是有相應錯誤,歡迎大佬指正,也歡迎你們可以一塊兒交流問題,但願能和你們一塊兒獲得成長!

相關文章
相關標籤/搜索