m_shige1979のささやかな抵抗と欲望の日々

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

javascriptのfetchを使ってAPIより結果を取得

概要

fetch使ってみたい

APIはgo言語で作成した適当なやつ

サーバ側
package main

import (
	"encoding/json"
	"log"
	"math/rand"
	"net/http"
	"time"
)

func main() {
	http.HandleFunc("/sample_api1", sampleAPI1)
	http.HandleFunc("/sample_api2", sampleAPI2)
	http.HandleFunc("/sample_api3", sampleAPI3)
	http.ListenAndServe("127.0.0.1:8080", nil)
}

// Response ...
type Response struct {
	Status int    `json:"status"`
	Rssult string `json:"result"`
}

func sampleAPI1(w http.ResponseWriter, r *http.Request) {

	//if r.Method == http.MethodOptions {
	//	return
	//}
	log.Println("api1", r.Method)
	rand.Seed(time.Now().UnixNano())
	time.Sleep(time.Duration(int(rand.Intn(5))) * time.Second)
	response := Response{http.StatusOK, "ok1"}
	res, _ := json.Marshal(response)

	r.Close = true
	defer r.Body.Close()
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "*")
	w.Header().Set("Accept", "application/json")
	w.Header().Set("Content-Type", "application/json")
	w.Write(res)

}
func sampleAPI2(w http.ResponseWriter, r *http.Request) {

	//if r.Method == http.MethodOptions {
	//	return
	//}
	log.Println("api2", r.Method)

	rand.Seed(time.Now().UnixNano())
	time.Sleep(time.Duration(int(rand.Intn(5))) * time.Second)
	response := Response{http.StatusOK, "ok2"}
	res, _ := json.Marshal(response)

	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "*")
	w.Header().Set("Content-Type", "application/json")
	w.Write(res)
}
func sampleAPI3(w http.ResponseWriter, r *http.Request) {

	//if r.Method == http.MethodOptions {
	//	return
	//}
	log.Println("api3", r.Method)

	rand.Seed(time.Now().UnixNano())
	time.Sleep(time.Duration(int(rand.Intn(5))) * time.Second)
	response := Response{http.StatusOK, "ok3"}
	res, _ := json.Marshal(response)

	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Headers", "*")
	w.Header().Set("Content-Type", "application/json")
	w.Write(res)
}

やって置かないとポートが違うとかなんとかでCORSエラーで弾かれる

javascript(Promise.all)
unction taskA() {
       
    return fetch("http://127.0.0.1:8080/sample_api1", {
        method: "GET", // *GET, POST, PUT, DELETE, etc.
        mode: "cors", // no-cors, cors, *same-origin
        cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
        credentials: "same-origin", // include, same-origin, *omit
        headers: {
            "Content-Type": "application/json; charset=utf-8",
        },
        redirect: "manual", // manual, *follow, error
        referrer: "no-referrer", // no-referrer, *client
        //body: JSON.stringify("{}"), // 本文のデータ型は "Content-Type" ヘッダーと一致する必要があります
    })
    .then(function(response) {
        console.log("taskA");
        return response.json();
    });
    
    
}
function taskB()  {

   return fetch("http://127.0.0.1:8080/sample_api2", {
        method: "GET", // *GET, POST, PUT, DELETE, etc.
        mode: "cors", // no-cors, cors, *same-origin
        cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
        credentials: "same-origin", // include, same-origin, *omit
        headers: {
            "Content-Type": "application/json; charset=utf-8",
        },
        redirect: "manual", // manual, *follow, error
        referrer: "no-referrer", // no-referrer, *client
        //body: JSON.stringify("{}"), // 本文のデータ型は "Content-Type" ヘッダーと一致する必要があります
    })
    .then(function(response) {
        console.log("taskB");
        return response.json();
    });

}
function taskC()  {

   return fetch("http://127.0.0.1:8080/sample_api3", {
        method: "GET", // *GET, POST, PUT, DELETE, etc.
        mode: "cors", // no-cors, cors, *same-origin
        cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
        credentials: "same-origin", // include, same-origin, *omit
        headers: {
            "Content-Type": "application/json; charset=utf-8",
        },
        redirect: "manual", // manual, *follow, error
        referrer: "no-referrer", // no-referrer, *client
        //body: JSON.stringify("{}"), // 本文のデータ型は "Content-Type" ヘッダーと一致する必要があります
    })
    .then(function(response) {
        console.log("taskC");
        return response.json();
    });

}

// 並列ですべて完了後にレスポンスを返却
console.log("start");
Promise.all([
    taskA(), taskB(), taskC()
]).then(function(data) {
    console.log("result start");
    console.log(data);
    console.log("result end");
});
console.log("end");

start
end
taskB
taskC
taskA
result start
(3) [{…}, {…}, {…}]0: {status: 200, result: "ok1"}1: {status: 200, result: "ok2"}2: {status: 200, result: "ok3"}length: 3__proto__: Array(0)
result end

※逐次処理も同じ感じで対応できそう

所感

今までajaxのcallbackでやってた部分が多いため、Promiseに対応していかないといけないが
ちょっと仕組みが難しく感じる
少しずつ確認して理解していくしかない…