ES4X 入門

ES4X 是什麼

ES4X是一款支持EcmaScript >=5應用的小型運行時。該運行時藉助vert.x並使用了graaljs實現。JavaScript是一個須要運行時支持的語言,但nodejs並不是惟一的運行時,JavaScript可不借助nodejs運行。 官網node

我的最喜歡ES4X的緣由是支持 await/async,要否則要寫不少 Futuremysql

簡單搭建一個 Restful Server

index.js

/// <reference types="@vertx/core/runtime" />
// @ts-check

import {BodyHandler, Router} from "@vertx/web";

const {helloHandler, authHandler, createBook, queryBook, queryBook2, updateBook, deleteBook} = require("./router/routes");

const app = Router.router(vertx);

app.route()
  .handler(BodyHandler.create())
  .handler(authHandler)
  .failureHandler(error => {
    console.error(error.failure());
    error.response().end("ERROR");
  });

app.get("/hello").handler(helloHandler);
app.post("/book").handler(createBook);
app.put("/book").handler(updateBook);
app.delete("/book").handler(deleteBook);
app.post("/queryBook").handler(queryBook);
app.post("/queryBook2").handler(queryBook2);

vertx.createHttpServer()
  .requestHandler(app)
  .listen(8090, server => {
    if (server.succeeded()) {
      console.log("server start ", server.result().actualPort());
    } else {
      console.error(server.cause());
    }
  });
複製代碼

router/routes.js

/// <reference types="@vertx/core/runtime" />
// @ts-check

import {MySQLClient, MySQLPool} from "@vertx/mysql-client";
import {SqlConnection, Tuple} from "@vertx/sql-client";
import {PoolOptions} from "@vertx/sql-client/options";
import {MySQLConnectOptions} from "@vertx/mysql-client/options";
import {Promise} from "@vertx/core";

const headerName = "Content-Type";
const headerValue = "application/json";

const countBookSQL = "SELECT COUNT(*) as count FROM Book";
const queryBookLimitSQL = "SELECT id, name, price FROM Book LIMIT ?,?";
const insertBookSQL = "INSERT INTO Book (name, price) VALUES (?,?)";
const updateBookSQL = "UPDATE Book set name=?, price=? where id = ?";
const deleteBookSQL = "DELETE FROM Book where id = ?";

let mysqlOption = new MySQLConnectOptions()
  .setPort(3306)
  .setHost("localhost")
  .setDatabase("sweet")
  .setUser("root")
  .setPassword("123456");

const poolOptions = new PoolOptions().setMaxSize(5);

const mysqlClient = MySQLPool.pool(vertx, mysqlOption, poolOptions);

async function getConn() {
  let p = Promise.promise();
  mysqlClient.getConnection(p);
  return await p.future();
}

async function updateSQL(sql, params) {
  let conn = await getConn();
  try {
    let resultPromise = Promise.promise();
    conn.preparedQuery(sql, params, resultPromise);
    let result = await resultPromise.future();
    let id = result.property(MySQLClient.LAST_INSERTED_ID);
    return {
      "rowCount": result.rowCount(),
      "id": id
    };
  } finally {
    conn.close();
  }
}

function getSqlToColumns(querySql) {
  let startIndex = querySql.indexOf("T") + 1;
  let endIndex = querySql.indexOf("FROM");
  return querySql.substring(startIndex, endIndex).split(",").map(t => t.trim());

}

function convertRowSet(columnList, rows) {
  let result = [];
  rows.forEach(row => {
    let item = {};
    for (let i = 0; i < columnList.length; i++) {
      let v = row.getValue(i);
      item[columnList[i]] = v ? v.toString() : 'null';
    }
    result.push(item);
  });
  return result;
}

// 適合簡單查詢,無需手動關閉鏈接
async function simpleQuery(sql, params) {
  let p = Promise.promise();
  mysqlClient.preparedQuery(sql, params, p);
  let rows = await p.future();
  let columns = getSqlToColumns(sql);
  return convertRowSet(columns, rows);
}

async function getBookCount(conn) {
  let p = Promise.promise();
  conn.preparedQuery(countBookSQL, p);
  let result = await p.future();

  for (let item of result) {
    return item.getLong(0);
  }
}

function printRows(rows) {
  rows.forEach(row => {
    console.log(row);
  });
}

async function queryBookLimit(conn, start, length) {
  let p = Promise.promise();
  conn.preparedQuery(queryBookLimitSQL, Tuple.of(start, length), p);
  let rows = await p.future();
  // printRows(rows);
  let columns = getSqlToColumns(queryBookLimitSQL);
  return convertRowSet(columns, rows);
}

async function manyQuery(start, length) {
  console.log("start: " + start + ", len: " + length);
  let conn = await getConn();
  try {
    let count = await getBookCount(conn);
    console.log("count: " + count);
    let bookArray = await queryBookLimit(conn, start, length);
    return {
      "total": count,
      "data": bookArray
    };
  } finally {
    conn.close();
  }
}

module.exports = {
  // 處理權限等操做
  authHandler: (ctx) => {
    console.log("authHandler...");
    ctx.next();
  },

  helloHandler: (ctx) => {
    ctx.response().end("hello " + Date())
  },

  queryBook: async (ctx) => {
    const body = ctx.getBodyAsJson();
    console.log("query body: " + body);
    let list = await simpleQuery(queryBookLimitSQL,
      Tuple.of(body.getInteger("start"), body.getInteger("length")));
    ctx.response()
      .putHeader(headerName, headerValue)
      .end(JSON.stringify(list))
  },

  queryBook2: async (ctx) => {
    const body = ctx.getBodyAsJson();
    console.log("body: " + body);
    let result = await manyQuery(body.getInteger("start"), body.getInteger("length"));
    ctx.response()
      .putHeader(headerName, headerValue)
      .end(JSON.stringify(result));
  },

  createBook: async (ctx) => {
    const body = ctx.getBodyAsJson();
    console.log("body: " + body);
    let result = await updateSQL(insertBookSQL,
      Tuple.of(body.getString("name"), body.getDouble("price")));
    ctx.response()
      .putHeader(headerName, headerValue)
      .end(JSON.stringify(result));
  },

  updateBook: async (ctx) => {
    const body = ctx.getBodyAsJson();
    let id = body.getInteger("id");
    let result = await updateSQL(updateBookSQL, Tuple.of(body.getString("name"), body.getDouble("price"), id));
    ctx.response()
      .putHeader(headerName, headerValue)
      .end(JSON.stringify(result));
  },

  deleteBook: async (ctx) => {
    let id = ctx.request().getParam("id");
    let result = await updateSQL(deleteBookSQL, Tuple.of(id));
    ctx.response()
      .putHeader(headerName, headerValue)
      .end(JSON.stringify(result));
  },

};
複製代碼

package.json

{
  "name": "es4x-hello",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "es4x-launcher test index.test.js",
    "postinstall": "es4x install",
    "start": "es4x-launcher"
  },
  "dependencies": {
    "@vertx/core": "^3.8.1",
    "@vertx/web": "^3.8.1",
    "@vertx/mysql-client": "^3.8.1",
    "@vertx/sql-client": "^3.8.1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
複製代碼

代碼地址

giteereact

相關文章
相關標籤/搜索