javascript で配列要素についてコールバックの処理を待つ方法
- 評価
- クリップ 0
- VIEW 1,145
前提・実現したいこと
Javascriptにて、
配列の各要素について、コールバック処理を待ってデータの代入をしようとしています。
コールバック処理の内容はデータのロードです。
model_data.Get_LoadState()でデータロードの状態を参照しています。
発生している問題・エラーメッセージ
単独の変数に対してコールバック処理を待って代入することはできましたが、
その処理を配列各要素に対して行う処理について記述できません。
単一変数での場合:
var Model;
var A = new ClassA();
function waitforload() {
if (A.model_data.Get_LoadState() == false) {
setTimeout(waitforload, 10);
return;
}
Model = A.model_data.Get_Model();
}
waitforload();
行いたい処理
var Model = new Array();
for(i=0;i<model_data.lungth;i++){
var A = new ClassA();
function waitforload() {
if (A.model_data.Get_LoadState() == false) {
setTimeout(waitforload, 10);
return;
}
Model[i] = A.model_data.Get_Model();
}
}
waitforload();
デバッグ時に確認できたこと、
Model[i] = model_data[i].Get_Model();
が実行されるときには、iが範囲外となり、参照うまくいきません。
コードは一部本来のものとは異なっております。
非常に困っておりまして、ご回答いただけるとありがたいです。
追記
three.jsを用いてjson形式で書きだしたデータをファイル名で読み出して、
取得データからメッシュを返すクラスを作りました。
C_Model = function() {
//ジオメトリを保持
this.Geometory = null;
//マテリアルを保持
this.Material = null;
//パーツ読み込み完了フラグ
this.LoadFlag = false;
//パーツファイル名
this.JSONfilename = false;
};
//保持しているジオメトリとマテリアルでメッシュを作って返す。
C_Model.prototype.Get_Model = function () {
var tmp = new THREE.Mesh(this.Geometory, this.Material);
return tmp;
};
//指定されたファイル名に基づいて、ジオメトリとマテリアルを取得
C_Model.prototype.Load_Model = function (JSONfilename) {
this.JSONfilename = JSONfilename;
var loader = new THREE.JSONLoader();
var obj = this;
var func = function (Geometory, Material) {
obj.Collback(Geometory, Material);
}
loader.load(JSONfilename, func);
};
C_Model.prototype.Collback = function(Geometory, Material) {
//console.log(Geometory);
//console.log(Material);
this.Geometory = Geometory;
this.Material = new THREE.MeshFaceMaterial(Material);
this.LoadFlag = true;
console.log("LOAD-"+this.JSONfilename+"-FINISH");
};
C_Model.prototype.Get_LoadState= function(){
return this.LoadFlag;
};
このクラスを用いて複数データのメッシュデータを得て、
それを配列要素に一つづつ読み込もうとしています。
こちらのクラスを使用して単一のモデルを読むだけであれば、
var model_data = new C_Model();
var Model = null;
model_data.Load_Model("model.json");
function waitforload() {
if (model_data.Get_LoadState() == false) {
setTimeout(waitforload, 10);
return;
}
Model = model_data.Get_Model();
scene.add(Model);
}
waitforload();
とすることでModelにデータを読み込めています。
modelを配列化してそれぞれにデータの取り込みをしたいと考えています。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+1
目的のコードを完全には掴みきれてませんが、配列を非同期に連続処理させたいコードと認識しました。
下記コードでどうでしょうか。
(「Promise
を使え」という声があがりそうですが)
'use strict';
function ClassA () {}
var models = [],
data = {length: 4};
setTimeout(function waitforload (models, length) {
models.push(new ClassA);
if (models.length < length) {
setTimeout(waitforload, 10, models, length);
} else {
console.log(models);
}
}, 10, models, data.length + 1);
Re: okutann0529 さん
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
checkベストアンサー
0
基本的にループ処理ではなく、イベントドリブンな処理にすると整理できます。
ここで言うイベントドリブンは、一つのファイルのロードが完了したら、それをトリガーとして次のファイルのロードを開始する、というのを繰り返すことで、すべてのファイルをロードする、という意味です。
例えば以下のように書くことができます。
var model_files = ['model1.json', 'model2.json', 'model3.json'];
var model_file_index = 0;
var models = [];
function loadNextModel()
{
var filename;
if (model_file_index < model_files.length) {
filename = model_files[model_file_index];
models.push({file: filename, model: new C_Model()});
models[model_file_index].model.Load_Model(filename);
model_file_index++;
} else {
console.log('全ファイルロード完了!');
}
}
loadNextModel(); // 一つ目のファイルのロードを開始する
まず、ループ処理を上記のように修正し、C_Model.prototype.Callback() を以下のように改造します。
C_Model.prototype.Collback = function(Geometory, Material) {
this.Geometory = Geometory;
this.Material = new THREE.MeshFaceMaterial(Material);
loadNextModel(); // 次のモデルデータをロードする
};
ご参考になれば。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
普通に無限ループかましちゃうのはダメなんですか?
var Model = new Array();
for(i=0;i<model_data.lungth;i++){
var A = new ClassA();
while ( !A.model_data.Get_LoadState() ) {}
Model[i] = A.model_data.Get_Model();
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.32%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
tkanda
2016/05/10 23:41
この model_data というのは、サーバーから ajax かなにかでロードしてるのですか?そのあたりを詳しく説明すると、回答が付きやすくなると思います。
okutann0529
2016/05/11 20:48
ソースコードを追加させていただきました。
model_dataはLoad_Modelでオブジェクトのjsonファイルのロードを行います。
ロード自体はTHREE.JSONLoader();のloadメソッドを利用しています。
わかりにくいところがあり申し訳ありませんが
よろしくお願いいたします。