Koa 

next generation web framework for node.js

Koa 洋蔥模型介紹

const Koa = require('koa');
const app = new Koa();

// x-response-time

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  ctx.set('X-Response-Time', `${ms}ms`);
});

// logger

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}`);
});

// response

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

Generator
Thunk
Co
Aysnc/Await

Node.js 

// 耗費時間M
getData('from_db');

// 耗費時間N
getData('from_remote_api', function (result) {});

Node.js 本身是 Javascript

單執行緒遇到阻塞I/O
提供異步編程

Node.js 

異步編程問題

fs.readFile('file1.txt', 'utf8', function (err, txt) {
  if (err) {
    throw err;
  }
  fs.readFile(txt, 'utf8', function (err, content) {
    if (err) {
      throw err;
    }
    console.log(content);
  });
});
fs.readFile('file1.txt', 'utf8', function (err, txt) {
  if (err) {
    throw err;
  }
  console.log(txt);
});
fs.readFile('file2.txt', 'utf8', function (err, content) {
  if (err) {
    throw err;
  }
  console.log(content);
});

如何避免 Callback Hell?

  1. ​自定義
  2. Promise/Deffered
  3. Higher Order Function
fs.readdir(path.join(__dirname, './index.js'), (err, files) => {
    files.foreach((filename, index) => {
        fs.readFile((filename, 'utf-8', (err, file) => {
            ...
        }))
    })
})

使用高階函數解法

var pending = (function () {
  var count = 0;
  return function (callback) {
    count++;
    return function () {
      count--;
      if (count === 0) {
        callback();
      }
    };
  };
}());

var done = pending(function () {
  console.log('all is over');
});

fs.readFile('file1.txt', 'utf8', done());
fs.readFile('file2.txt', 'utf8', done());

https://repl.it/repls/JampackedDarkmagentaClimate

Generator Intro

  • 在 Generator 出現以前,函數只有 use 跟 not use 的情況
  • 基本定義
  • 使用 yield 的暫停效果
  • 查看 next 結果挾帶的狀態
  • 可利用 next 傳遞參數,傳回 yield 前面的變數

Thunk

  • 編譯器的求值策略 -   傳值調用 vs 傳名調用

var x = 1;

function f(m) {
  return m * 2;     
}

f(x + 5);


// 傳值調用
// 先計算

f(x+5)

f(6)


// 傳名應用
// 只在用到時才計算

f(x + 5)

f(x + 5 * 2)
// 哪一個好?
// 傳值應用比較簡單,但以下範例就會做不必要求值

function f(a, b){
  return b;
}

f(3 * x * x - 2 * x - 1, x);

Thunk 定義

  • 傳名調用 - 將參數放到臨時函數裡,再將臨時函數放到函數裡
  • 此臨時函數就是 - Thunk
function f(m){
  return m * 2;     
}

f(x + 5);

// 等同于

var thunk = function () {
  return x + 5;
};

function f(thunk){
  return thunk() * 2;
}

Javascript 裡的 Thunk

  • 將多參數函數轉為單參數函式,且參數只接受 callback
// 正常版本的readFile(多參數本)
fs.readFile(fileName, callback);

// Thunk版本的readFile(單参数版本)
var readFileThunk = Thunk(fileName);
readFileThunk(callback);

var Thunk = function (fileName){
  return function (callback){
    return fs.readFile(fileName, callback); 
  };
};

Thunk + Generator

Co

  • 使用 Promise 
  • 不需編寫 Generator 執行器

Flow 並發執行

Aysnc / Await

  • generator + yield 的語法糖
  • async 函数就是將 Generator 函数的星號(*)替换成 async,将 yield 替换成 await,僅此而已

  • 就字面上意思也更好理解

說好的洋蔥呢

講到這大家都累了...

一行入魂,ㄜ不是,一張 Gif 解釋洋蔥蔥

Made with Slides.com