LoginSignup
27
24

More than 5 years have passed since last update.

ブラウザで非同期処理を同期的に処理する fetch(Promise) + async/await

Last updated at Posted at 2017-11-26

目的

Webアプリケーションを作成する際に、一旦サーバ上の設定ファイルやレンダリング用のモデルデータを事前に読み込んでおきたい場合に、どうしてもシーケンシャル(同時にアクセスしたくない場合)がある。jQueryのDeferredでも同じことができるが、fetch、async/awaitを用いることでもっと単純に処理ができるので、備忘として記載する。同じことを示した記事はいろいろとあるけど、どれもsetTimeoutやjQueryのDeferred、generatorなどの経緯も込みで書いてあるので、それはそちらにまかせて、ここではfetch + async/awaitのみを書く。

fetch + async/await

これでOK

getConfig = async() => {
    var conf1 = await (await fetch("/conf/conf1.yml?_="+(new Date()).getDate())).text();
    console.log(conf1);
    var conf2 = await (await fetch("/conf/conf2.yml?_="+(new Date()).getDate())).text();
    console.log(conf2);
}

window.onload = function(){
    getConfig();
}

fetchやfetchの text() / json() / blob() などはPromiseを返却するので、以下のように書くと理屈がわかりやすい。

getConfig = async() => {
    var promise1 = await fetch("/conf/conf1.yml?_="+(new Date()).getDate());
    var conf1 = await promise1.text();
    console.log(conf1);
    var promise2 = await fetch("/conf/conf2.yml?_="+(new Date()).getDate());
    var conf2 = await promise2.text();
    console.log(conf2);
}

window.onload = function(){
    getConfig();
}

fetchの代わりに、Promiseを返却する関数を指定しても同じことができる。
また、fetchは4xx系、5xx系のエラーコードが返却されても、正常処理としてしまうので、try catchが使えない。※ネットワーク系のエラーの場合のみcatchが使える。4xx、5xx系はstatusを見て判断しろという事らしい。
そのため、エラーハンドリングをしたい場合は以下のようにすることができる。

getConfig = async() => {
    var conf1 = await (await fetch("/conf/conf1.yml?_="+(new Date()).getDate())
                    .then(handler)
                    .catch(error)
                ).text();
    console.log(conf1);
    var conf2 = await (await fetch("/conf/conf2.yml?_="+(new Date()).getDate())
                    .then(handler)
                    .catch(error)
                ).text();
    console.log(conf2);
}

function handler(response){
    if(!response.ok){
        throw Error(response.statusText);
    }
    return response;
}

function error(e){
    console.log(e);
}

window.onload = function(){
    getConfig();
}

まとめ

  • fetch は Promise を返却する
  • await は async なメソッドの中でのみ実行可能
  • await は Promise を待つ
  • 上記のコードは、getConfig() 自体が同期になるわけではない。
  • 上記のコードは python -m SimpleHTTPServer 80 では動かないので注意
  • トランスパイルなんてしたくない!!古いブラウザは捨てたい!!
    大企業の古いブラウザバージョンいつまでもケアは頭がおかしい。

添付

27
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
24