#GolangのレスポンスデータをjsのPromiseをリターンするfetch APIで取得する
こちらでXMLHttpRequest
を利用したPOSTによるデータ受信をPromiseで実現したが、PHPではなく、Golangで作成したWebアプリケーションを用意する。
また、XMLHttpRequest
ではなく、JS標準のPromiseをリターンするfetch API
を利用してみた。
なお、ここでも、シナリオはPOSTでJSONデータを利用するシナリオ(シナリオ1)と、POSTでCSVを受信するシナリオ(シナリオ2)の2パターンを記載。
##サンプルのディレクトリ構成
Golangが動作する環境であること。Golangのインストール方法については、公式サイト等を参照。
test.csv
の内容については割愛。
./demo.go
./test.csv
./template/scenario1.htm
./template/scenario1.htm
./static/css/modal.css
./static/js/app1.js
./static/js/app2.js
./static/js/bundle1.js
./static/js/bundle2.js
./static/js/libs/MyLoader.js
##jsサンプルコードのビルド方法(bundle1.jsとbundle2.jsの作成方法)について
ここでもes6で用意した。ビルド方法については、こちらを参照。
##Golangを使ったWebアプリケーション
シナリオ1、シナリオ2、JSONおよびCSVデータをレスポンスするのに、http.HandleFunc
を使い、cssやjsはhttp.Handle
で応答するように実装した。
###Golangのサンプルコード
go run demo.go
と実行すると、例えばhttp://localhost:3001/json
でアクセスするとJSONデータのレスポンスが確認できる。
/csv
、./json
にPOST以外でアクセスしたときは、"Method Not Allowed"(ステータスコード405)でレスポンスするようにした。
package main
import (
"fmt"
"encoding/json"
"net/http"
"html/template"
)
type MyJson struct {
Status string `json:"status"`
Value int `json:"value"`
}
type MyContent struct {
Scene int
}
func main() {
http.HandleFunc("/scenario1", viewScenario(1))
http.HandleFunc("/scenario2", viewScenario(2))
http.HandleFunc("/json", responseJson)
http.HandleFunc("/csv", func (w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "POST":
http.ServeFile(w, r, "./test.csv")
default:
w.WriteHeader(405)
w.Write([]byte("Method Not Allowed!"))
}
})
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
http.ListenAndServe(":3001", nil)
}
func viewScenario(scene int) func (w http.ResponseWriter, r *http.Request) {
return func (w http.ResponseWriter, r *http.Request) {
mc := MyContent {scene}
tmpl, err := template.ParseFiles(fmt.Sprintf("template/scenario%d.htm", scene))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := tmpl.Execute(w, mc); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}
func responseJson(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "POST":
mj := MyJson {"SUCCESS", 100}
js, err := json.Marshal(mj)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(js)
default:
w.WriteHeader(405)
w.Write([]byte("Method Not Allowed!"))
}
}
##ローダー
こちらと同様にダウンロード中にローダを表示するようにした。
###JSのサンプルコード
"use strict"
const modal = document.createElement("div");
modal.className = "modal";
export default class MyLoader {
constructor() {
this.loading = document.createElement("div");
this.loading.className = "loader";
}
show() {
modal.appendChild(this.loading);
document.body.appendChild(modal);
}
hide() {
document.body.removeChild(modal);
modal.removeChild(this.loading);
}
}
###cssのサンプルコード
.modal {
width: 100%;
height: 300px;
}
.loader {
margin: 150px auto;
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid blue;
border-right: 16px solid green;
border-bottom: 16px solid red;
border-left: 16px solid pink;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
##シナリオ1
POSTしてJSONデータを受信し、その内容を描画する。
###テンプレート
Golangのサンプルコード中の処理template.Execute
で、タイトルタグのScene
の値(ここでは1
)が設定される。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Scenario{{ .Scene }}</title>
<link rel="stylesheet" type="text/css" href="/static/css/modal.css">
</head>
<body>
<div style="margin: 20px" class="js-json">
<div style="color: red" class="js-json-message"></div>
<input type="button" post_url="/json" class="js-json-post" value="JSON">
</div>
<footer>
<script type="text/javascript" src="/static/js/bundle1.js"></script>
</footer>
</body>
</html>
###jsのサンプルコード
response.json()
とすることで、JSONデータを受信できる。
"use strict"
import MyLoader from "./libs/MyLoader";
class MyApp {
static exec() {
const obj = new MyApp();
const target = document.querySelector(".js-json");
target && obj.setupJson(target);
}
setupJson(target) {
const url = [
location.protocol + '//',
location.host
];
const buttons = target.querySelectorAll(".js-json-post");
[].forEach.call(buttons, (button) => {
button.addEventListener("click", (evt) => {
evt.preventDefault();
let post_url = url.join('') + button.getAttribute("post_url");
const loading = new MyLoader();
loading.show();
fetch(post_url, {method: 'POST'}).then((response) => {
return response.json();
}).then((json) => {
const msg = target.querySelector(".js-json-message");
msg.innerHTML = json.value;
loading.hide();
}).catch(() => {
loading.hide();
alert('通信に失敗しました');
});
});
});
}
}
MyApp.exec();
##シナリオ2
POSTでCSVデータを受信するケース。
###テンプレート
シナリオ1と同様にGolangのサンプルコード中の処理template.Execute
で、タイトルタグのScene
の値(ここでは2
)が設定される。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Scenario{{ .Scene }}</title>
<link rel="stylesheet" type="text/css" href="/static/css/modal.css">
</head>
<body>
<div style="margin: 20px" class="js-csv">
<input type="button" post_url="/csv" class="js-csv-post" value="csv">
</div>
<footer>
<script type="text/javascript" src="/static/js/bundle2.js"></script>
</footer>
</body>
</html>
###jsのサンプルコード
response.blob()
でBlobオブジェクトが取得できるので、a
タグを作成して、クリックイベントを発生させることでダウンロードできる。
"use strict"
import MyLoader from "./libs/MyLoader";
class MyApp {
static exec() {
const obj = new MyApp();
const target = document.querySelector(".js-csv");
target && obj.setupCsv(target);
}
setupCsv(target) {
const url = [
location.protocol + '//',
location.host
];
const buttons = target.querySelectorAll(".js-csv-post");
[].forEach.call(buttons, (button) => {
button.addEventListener("click", (evt) => {
evt.preventDefault();
let post_url = url.join('') + button.getAttribute("post_url");
const loading = new MyLoader();
loading.show();
fetch(post_url, {method: 'POST'}).then((response) => {
return response.blob();
}).then((blob) => {
const URL = window.URL || window.webkitURL;
const bu = URL.createObjectURL(blob);
const a = document.createElement('a');
a.download = "test.csv";
a.href = bu;
a.click();
loading.hide();
}).catch(() => {
loading.hide();
alert('通信に失敗しました');
});
});
});
}
}
MyApp.exec();
##シナリオの実行方法
go run demo.go
と実行するWebアプリケーションが起動するので、その状態で、http://localhost:3001/scenario1
やhttp://localhost:3001/scenario2
にアクセス。