「プロミス処理のラッパーをつくる」という記事でつくった Promise ラッパーで非同期処理が捗っているので進捗報告。
(追記) ここで書いた関数は Promise のアンチパターンである "explicit construction" になってて、それで Promise チェーンが機能してなかった。恥ずかしながら、修正しました。
n * 1000 ミリ秒間隔で n 回再試行
Promise 化した処理をタイトル通り繰り返し処理したい時に使える関数:
var count = function (done, times, interval) {
return done()
.then(function (dat) {
return dat;
}, function (err) {
if (1 >= times) return err;
return sleep(interval) // 下記で解説
.then(function () {
return count(done, times - 1, interval);
});
});
};
// ※ 当初 `promisify` 高階関数でラップしてたけど、不要だしアンチパターンでした。お恥ずかしい。
使用例
// Underscore.js と jQuery が必要
var ajaxOpts = {
data: { foo: 'bar' },
method: 'GET'
};
count(_.bind($.ajax, undefined, '//example.com/no/existence', ajaxOpts), 3, 1000)
.then(function (resp) {
// 1 秒間隔で最大 3 回再試行してレスポンスが得られた場合
}, function (jqXHR) {
// 1 秒間隔で最大 3 回再試行してエラーだった場合
});
上記例は複雑なパターンだけど、$.ajax
が Promise を返す関数なので、それを count
に渡すと、1 秒間隔で最大 3 回再試行してくれる。count
は高階関数じゃないので、$.ajax
の引数が受けられない。なので、_.bind
で $.ajax
にも然るべき引数を与えている。
依存関数
上記関数内で使用している Promise タイマー関数はこちら:
// 「プロミス処理のラッパーをつくる」でつくった `promisify` 関数が必要
var sleep = promisify(function (resolve, reject, millisec) {
if (!millisec) millisec = 80;
var timeoutId = setTimeout(function () {
clearTimeout(timeoutId);
resolve(millisec);
}, millisec);
});
n * 1000 ミリ秒間に可能な限り再試行
こっちは制限時間内に可能な限り繰り返し処理したい時に使える関数:
// Underscore.js が必要
var tick = function (done, duration, start) {
if (!_.isNumber(start)) start = +(new Date());
return done()
.then(function (dat) {
return dat;
}, function (err) {
var stop = +(new Date());
if (duration > stop - start) return tick(done, duration, start);
return err;
});
};
// ※ 当初 `promisify` 高階関数でラップしてたけど、不要だしアンチパターンでした。お恥ずかしい。
使用例
// Underscore.js と jQuery が必要
var ajaxOpts = {
data: { foo: 'bar' },
method: 'GET'
};
tick(_.bind($.ajax, undefined, '//example.com/no/existence', ajaxOpts), 3000)
.then(function (resp) {
// 3 秒間に可能な限り再試行してレスポンスが得られた場合
}, function (jqXHR) {
// 3 秒間に可能な限り再試行してエラーだった場合
});
これは前述のパターンと同じなので省略。
これ捗りそう...!