LoginSignup
1
1

More than 5 years have passed since last update.

クラス内でのアロー関数のthis

Last updated at Posted at 2017-11-26

目的

JavaScriptにおけるクラスの中でasync/awaitを使う際にハマりそうな箇所があったので備忘

クラス内でasync/awaitを使う

動くコード

function myClass(){
    this.value = 1;
}

myClass.prototype.run = async function() {
    this.value = await new Promise((resolve,reject) => {
        setTimeout(function(){
            return resolve(2);
        },100);
    });
    this.show();
}

myClass.prototype.show = function(){
    console.log(this.value);
}

var c = new myClass();
c.run();

動かないコード

function myClass(){
    this.value = 1;
}

myClass.prototype.run = async() => {
    this.value = await new Promise((resolve,reject) => {
        setTimeout(function(){
            return resolve(2);
        },100);
    });
    this.show();
}

myClass.prototype.show = function(){
    console.log(this.value);
}

var c = new myClass();
c.run();

↓ 違い

myClass.prototype.run = async function() {
myClass.prototype.run = async() => {

上のコードは意図した動きになるが、下のコードはちゃんと動かない。this が myClassインスタンス をポイントしていない。
まぁ当然といえば当然か。

指摘を踏まえて、最終的にやりたかったことを書いてみた。最終的には、yamlで定義されたglTFの情報を読み込んでごにょごにょと処理をしたい場合に、three.jsのglTFローダが非同期なので、一度読み込んだglTFをうまいこと再利用してオブジェクトを生成したいなということ。
以下で一応やりたいことは実現できた。kentaro1530さん、どうもありがとう。

index.html
<!DOCTYPE html>
    <head>
        <script src="lib/js-yaml/js-yaml.min.js"></script>
        <script src="lib/three.js/three.min.js"></script>
        <script src="lib/three.js/loaders/GLTFLoader.js"></script>
        <script src="js/myClass.js"></script>
    </head>
    <body>
    </body>
</html>
myClass.js
class MyClass{
    constructor(){
        this.gltfs = {};
        this.config;
        this.loader = new THREE.GLTFLoader();
        this.getConfig();
    }

    async getConfig(){
        var configString = await (
            await fetch("/public/config.yml?_="+(new Date()).getDate())
                .then(this.configHandler)
                .catch(this.configError)
        ).text();
        this.config = jsyaml.load(configString);
        this.loadModels();
    }

    async loadModels(){
        console.log(this.config);
        for(var modelName in this.config.model){
            var model = this.config.model[modelName];
            if(this.gltfs[model.gltf] == null){
                var gltfObj = await new Promise((resolve,reject) => {
                    this.loader.load(model.gltf+"?_="+(new Date()).getTime(), function(data) {
                        return resolve(data.scene);
                    }, undefined, function ( error ) {
                        return reject(null);
                    });
                });
                model.gltfObj = gltfObj;
                this.gltfs[model.gltf] = gltfObj;
            } else {
                model.gltfObj = this.gltfs[model.gltf].clone();
            }
        }
    }

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

    configError(e){
        console.log(e);
    }

}

myClass = new MyClass();
public/config.yml
model:
  model1:
    gltf: public/data1.gltf

  model2:
    gltf: public/data2.gltf

  model3:
    gltf: public/data1.gltf
1
1
2

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
1
1