iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 9
0
自我挑戰組

Some thing with Reason系列 第 9

Reason - Express-helloworld-API

  • 分享至 

  • xImage
  •  

Express API

之前聊了很多基本的型態和使用

開始來做一些實際的東西(不然有點無聊)

Nodejs 中似乎想到 API

都會先想到 Express

今天先用 Reason 寫一個 Express 的 hello world API

但是在這之前

我們先用最簡單的 nodejs 寫一個 Express hello world API

然後再慢慢轉為 Reason

Hello world

安裝 express 和開始 watch re 檔案

  $ npm install express
  $ yarn start 

app.js

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => res.send('Hello World!'));

app.listen(port);

Image

步驟

在上面的範例中 require 了一個 express 他是一個函式 它會回傳一個 app 的物件

然和對 app 的這個物件 有使用到兩個函式

listenget

listen 會丟入一個參數(int)

get 會丟入兩個參數(string, function)

而在 get 中丟入的 function 會有兩個物件 req, res

因為只有使用到 res.send

大致上我們可以先宣告剛剛有提到函式 和參數的類型

再寫上 express 的程式

結果如下

type res = {.
  [@bs.meth] "send": string => string
 };
type handler = (string, res) => string;
type expressApp = {.
  [@bs.meth] "listen": (int) => unit,
  [@bs.meth] "get": (string, handler) => string
};

[@bs.module] external express: unit => expressApp = "express";

let app = express();

app##get("/", (_, res) => res##send("Hello World!"));

app##listen(3000);

有一些東西看不懂

BuckleScript - Class

裡面有些東西和 BuckleScriptClass 有關係

先來聊聊 在 Reason 中如何使用 class new 出一個物件

@bs.new

Date 為範例

type t;
[@bs.new] external createDate: unit => t = "Date";

let date = createDate();

上面的程式碼會編譯為

var date = new Date();

如果你想要用 moment

可以利用 @bs.new@bs.module

並且設定回傳可以使用的 method

type momentResult = {.
  [@bs.meth] "format": (string) => string
};

[@bs.new] [@bs.module]  external moment: unit => momentResult = "";

let date = moment();
Js.log(date##format("YYYY"));

上面的程式碼會轉為

var Moment = require("moment");

var date = new Moment();

console.log(date.format("YYYY")); /* 2018 */

主要是因為在 moment 增加一個回傳的 momentResult 的類型

代表回傳了一個 Javascript 物件 裡面有一個 format 的函式可以使用

需要傳入一個 string 會回傳一個 string

綁定 JS Class

JS Class 其實就是 Object 和 Class 利用一些方式連接起來

OCaml 通常會增加 [@bs] 將 class 轉為 Js.t 類型

class type _moment =
  [@bs]
  {
    pub format: (string) => string;
  };
type momentResult = Js.t(_moment);

[@bs.new] [@bs.module]  external moment: unit => momentResult = "";
let date = moment();
Js.log(date##format("YYYY")); /* 2018 */

這個做法也是可以

結果是同樣的

但是這個做法可以使用 [@bs.meth] 來宣告非 arrow function

這些值會被視為 properties

[@bs.set] 則會將這些參數視為可以更動的 (mutable)

之後要修改值的時候要使用 #=

刪除 [@bs.set] 則會變為 不可變動的(immutable)

這部分之後在 JS package 中會做更詳細的討論

Middleware

先實做一個 簡單的 Middleware

type res = {.
  [@bs.meth] "send": string => string
 };

type nextFun = unit => string;
type handler = (string, res, nextFun) => string;

type expressApp = {.
  [@bs.meth] "listen": (int) => unit,
  [@bs.meth] "get": (string, handler, handler) => string
};

[@bs.module] external express: unit => expressApp = "express";

let app = express();

app##get("/", (_, _, next) => {
  Js.log("hello next");
  next();
}, (_, res, _) => res##send("Hello World!"));

app##listen(3000);

但是每次多一個 middleware 都要對一個 type 做一次修改

感覺很麻煩啊

今天先到這邊吧

之後再來處理 Middleware 的問題了


上一篇
BasicType-Module and Functor
下一篇
Express-Middleware
系列文
Some thing with Reason30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言