theContent
コールバックとしてではなく、直線(手続き型)で要求している部分。
.done(function (content) { doStuff(content); });
または、doStuff
使用せずthis
、他に何もする必要がない.done(doStuff);
場合は、コンテンツが戻ってきたときにdoStuffがコンテンツとともに起動されます。
loadImage = function () {}; // returns promise
showImage = function (image) {} // shows image
var imageLoading = loadImage("img/huge-img.bmp");
imageLoading.done(showImage);
または、さらにクリーンにするために、promiseshowImage
を使用するようにビルドします(関数内のコールバックをサブスクライブします)。
function showImage(promise) {
promise.done(function (img) {
document.body.appendChild(image);
});
今、あなたは持っています
var image = loadImage("huge-img.bmp");
showImage(image);
約束を使用します。完全に自然に見えます。
再編集 :名前空間
コールバック内で行う唯一のこととして、リストに物事をプッシュしたくないでしょう。
リストを使用しているのは何ですか?
theList.push()
と同じ名前のカスタム関数はありますが、余分[].push()
なものはありますか?
それとも単なる配列ですか?
問題は次のとおりです
。AJAXコールバックと同様に、Promiseは、次の処理に進む前に、処理が終了するのを待ちません。
したがって、プログラムがその配列で何かを行おうとしているdone
場合(配列に最終的にデータが含まれる場合)、それらの関数は空の配列で機能します。
代わりに、メソッド(コールバック)を使用してPromiseのリターンを処理する必要があります。
// these both do the same thing
/* ... */ .done(function (data) { NAMESPACE.module.callback(data); });
/* ... */ .done(NAMESPACE.Module.callback.bind(NAMESPACE.Module));
// if NAMESPACE.Module.callback ***does not use `this`*** you can write
/* ... */ .done(NAMESPACE.Module.callback);
// if you are unsure for even a second, do one of the other two calls
コールバックのデータをさらに処理する必要がある場合は、次のようにします。
/* ... */ .done(function (data) {
var arr = doStuff(data);
arr.forEach(function (obj) {
NAMESPACE.Module.list.push(obj);
});
NAMESPACE.Module.callback_relying_on_list();
});
ここでの2つのキーは次のとおりです。
this
コールバックでそれが正しいことを確認してください
- 約束の範囲内で作業します-それらのポイントは、準備ができているかどうかを確認するためにタイマーを設定する必要がないようにすることです...したがって、値を設定しているだけで、誰にもそれらが準備できていることを伝えていない場合準備ができて、約束はその仕事をしていません
編集#2 re:ソース
ここで行っていることを見てください(簡略化):
// a.js
function getFiles () {
GLOBAL.list = [];
getAsyncData().done(function (text) {
GLOBAL.list.push({ content : text });
});
}
//b.js
GLOBAL.Messages = {
write : function (messages) {
messages.forEach(/* ... */);
},
ready : function () { alert(GLOBAL.list.length); } }
};
// main program
getFiles();
GLOBAL.Messages.ready();
GLOBAL.Messages.write(GLOBAL.list);
これがあなたの正確なコードではないことは知っていますが、その単純化された状況を少し見てみましょう。
getFiles
関数が完全に機能しているのに、サーバーが30秒間データを返送しない場合はどうなりますか?
私ready
とwrite
関数はそれが起こるのを待つつもりはありません。
私getFiles
が終わったらすぐに発砲します。
だからここでは、あなたは間違った場所でその約束を持っています。
それは100%正しい方法と呼ばれていますが、なぜこれをしないのですか?
// a.js
function getFiles () {
var filesLoaded = getAsyncData(); // I'm collecting the promise, not chaining it.
// again, simplified
filesLoaded.done(function (text) { GLOBAL.list.push({ content : text}); });
// ***super important part***
return filesLoaded;
}
// b.js
/* ... */ = {
ready : function (promise) {
promise.done(function () { alert(GLOBAL.list.length); });
},
write : function (promise) {
promise.done(/* write the list */);
}
}
これで、メインは次のようになります。
var files = getFiles(); // files is the promise
// files.done, files.then, etc
GLOBAL.Messages.ready(files); // giving the promise to the method
// ready(promise) will subscribe to promise.done
GLOBAL.messages.write(files); // so will write(promise);
このようにpromiseを操作するときは、私の例はチェーン files
に追加したものとまったく同じオブジェクトであることを忘れないでください。.done()
また、関数がpromiseが返す値を気にする場合もあれば、promiseがいつ実行されるかを関数が知りたいだけなので、タイマーを設定してチェックする代わりに、後で発生する必要があることを実行できることも覚えておいてください。 。
そして、同期データを処理しているときはいつでも約束をとるクリーンアップされた関数を使用すると、次のことが可能になります。
var files = readTextFromFiles();
/* ... */.ready(promise);
ready
これが行っていることと古い準備ができていることの間に位置するために、もう1つの機能が必要であることを意味しますか?
まあ、そうだろう...
しかし、あなたの機能が早く消えないことを知っておく価値はあります。
そして、それは100%同期している間、ネストなしで本当にきれいに見えます。
急いでいる場合、またはこれらの他の関数を編集できない場合は、ページの下部にあるものをブートストラップするという悪い考えを行う可能性があります。
(function (promise) { promise.done(function () {
/* ... everything() ... */ });
}(files));
醜くて区別するのが難しく、別々のページで編集する必要がありますが、少なくともそれはまだ非同期であり、それでも順番に物事を行っています。
しかし、それでも、約束を返して収集し、渡すことを意味します。
お役に立てば幸いです。