先日、
ES6について書いた派生で Promise を見てたら、
ちょっと気になることを発見しました。
というか、
そういえば意識したこと無かった、
という感じですが(^_^;)
ときに、Promise というのは、
非同期処理を一意に扱えるようになるオブジェクトで、
ES6で導入される予定になっています。
ブラウザによっては既に使用可能になっているようです。
Promise の学習を目的としたこちらのページを参照していた所、
「同期と非同期の混在の問題」というのに目が止まりました。
ざっくり言うと、
呼び出される順番が期待したようにならない場合があるので、
非同期コールバックを同期的に呼び出してはいけない
ということです。
内容を読んでみるとナルホド納得。
このことを意識せず非同期処理を書いていたので一つ勉強になりました。
要するに、
完了が非同期になるものとして呼び出したのに、
即完了して同期呼び出しになる場合があるのは良くない
ということです。
先のページから引用するとこんな感じ。
まず、好ましくない例。
function onReady(fn) {
var readyState = document.readyState;
if (readyState === 'interactive' || readyState === 'complete') {
fn();
} else {
window.addEventListener('DOMContentLoaded', fn);
}
}
onReady(function () {
console.log('DOM fully loaded and parsed');
});
console.log('==Starting==');
そして、好ましい例。
function onReady(fn) {
var readyState = document.readyState;
if (readyState === 'interactive' || readyState === 'complete') {
setTimeout(fn, 0);
} else {
window.addEventListener('DOMContentLoaded', fn);
}
}
onReady(function () {
console.log('DOM fully loaded and parsed');
});
console.log('==Starting==');
違いは setTimeout
を使っているかどうかです。
fn
をそのまま呼ぶと同期になってしまうので、
非同期になるように setTimeout(fn, 0)
するというわけですね。
重要なのは、
Promise を使うと非同期で処理されることが保証されるので、
上記のような問題は起きないということです。
さらに、
コールバック地獄から開放されるという利点もあります(^_^;)
まぁ、これは書き方次第でどうにかなるようにも思いますが、
処理の流れがパット見で分かりやすくなるのは間違いなさそうです。
そんなわけで、
非同期処理する際は積極的に Promise を使って行きたい所ですが、
現状ではまだ対応してないブラウザとかあるようなので、
注意しながら従来通りの書き方でやるか、
こちらに書いてあるようなライブラリを使うかのどちらかになりそうですね。