目的
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