コンテンツへスキップ

非同期処理を同期処理のように扱うには

by : 2017/05/09

JavaScriptで常に問題になるのが非同期処理ではないでしょうか。かつてのコールバック地獄であったり、現在のPromiseによる処理など常に非同期処理に起因しています。そこで苦労されている方も多いでしょう。

例えばAjaxを使う際など、関数の戻り値としてPromiseを返すことがあります。

function ajax() {
return $.ajax({
url: '/'
});
}
function main() {
let p = ajax();
}

view raw
index.js
hosted with ❤ by GitHub

このような形の場合、返り値を受け取った側では必然的に一つネストが発生します。

function main() {
let p = ajax();
p.then(function(results) {
// Ajaxの処理成功時
})
}

view raw
index.js
hosted with ❤ by GitHub

コールバック時ほどではありませんが、ネストが深くなるのを嫌がる人は多いでしょう。そこで使えるのが次のような実装です。ネストが一段低くなっているのが分かるでしょうか。

function main(results) {
if (!results)
let p = ajax();
if (typeof p == 'object' && typeof p.then == 'function') {
p.then(function(results) {
main(results);
return;
})
}
// Ajaxの処理成功時
}

view raw
index.js
hosted with ❤ by GitHub

ajax関数の返値がPromiseオブジェクトであれば(then関数が定義されていれば)、処理を実行して結果を自分自身(main関数)に渡します。2回目に実行されたmain関数ではresultsが入っていますのでajax関数は実行しません。その結果、ajax関数の結果(results)をネストを深くすることなく利用できます。

hifiveで実装するには

実はhifiveにおいてコントローラ側で処理を実行する際には常にこのように実装されています。関数の引数がPromiseであれば、まず処理を実行して結果を再度自分自身に渡します。こうすることで無闇にネストが深くなるのを防いでいます。

if (h5.async.isPromise(data)) {
data.done(this.own(function(d) {
this.setData(d);
}));
return;
}

view raw
index.js
hosted with ❤ by GitHub


JavaScriptを使った開発で嫌がられるのが非同期処理に伴うネストが深いコードになります。ちょっとした工夫で防げますのでぜひ活用してください。

From → hifive

コメントは受け付けていません。

%d人のブロガーが「いいね」をつけました。