;(function ($) {
"use strict";
/**
* 時間管理時のDeferred実装用Deferredオブジェクト
* @typedef jQueryTimeDeferred
* @type {jQuery.Deferred}
* @property {Function} clear タイマーをキャンセルさせる為のメソッド
*/
/**
* setInterval の Deferred 実装
* $.interval(time) の様に呼び出す。
* 戻り値は Promise で、 関数として .clear() が追加されている。
* .done - 未使用
* .fail - 関数 .clear() を実行することにより呼ばれる
* .progress - timeミリ秒ごとに呼ばれる
* $.interval(time) では コールバックのthis に null が入るのに対して
* $(sel).interval(time) では コールバックの this に 選択設定した要素が入る。(画面上に存在しているかは非保証)
* @param {!Number} [time] time秒毎に繰り返す時間 (ms)
* @return {jQueryTimeDeferred}
*/
var interval = function (time) {
if (typeof time !== "number") {
time = interval.options.defaultInterval;
}
var self = this,
d = $.Deferred(),
key = setInterval(function () {
d.notifyWith(self);
}, time),
p = d.promise();
p.clear = function () {
clearInterval(key);
d.rejectWith(self);
};
return p;
};
interval.options = {
defaultInterval : 100
};
/**
* setTimeout の Deferred 実装
* $.timeout(time) の様に呼び出す。
* 戻り値は Promise で、 関数として .clear() が追加されている。
* .done - timeミリ秒経過して余裕があれば呼ばれる(余裕が無ければ余裕があるタイミングで呼ばれる)
* .fail - 関数 .clear() を実行することにより呼ばれる
* .progress - 未使用
* $.timeout(time) では コールバックのthis に null が入るのに対して
* $(sel).timeout(time) では コールバックの this に 選択設定した要素が入る。(画面上に存在しているかは非保証)
* @param {Number} [time] time秒後に呼び出す予定の時間 (ms)
* @return {jQueryTimeDeferred}
*/
var timeout = function (time) {
if (typeof time !== "number") {
time = timeout.options.defaultTime;
}
var self = this,
d = $.Deferred(),
key = setTimeout(function () {
d.resolveWith(self);
}, time),
p = d.promise();
p.clear = function () {
clearTimeout(key);
d.rejectWith(self);
};
return p;
};
timeout.options = {
defaultTime : 1
};
/**
* @param {Number} [time]
* @return {jQueryTimeDeferred}
*/
$.interval = function (time) {
return interval.call(null, time);
};
/**
* @param {Number} [time]
* @return {jQueryTimeDeferred}
*/
$.fn.interval = function (time) {
return interval.call(this, time);
};
/**
* @param {Number} [time]
* @return {jQueryTimeDeferred}
*/
$.timeout = function (time) {
return timeout.call(null, time);
};
/**
* @param {Number} [time]
* @return {jQueryTimeDeferred}
*/
$.fn.timeout = function (time) {
return timeout.call(this, time);
}
})(jQuery);
//テスト
;(function($){
$(function(){
var $result = $("#result"),
dTimeoutClear = null,
dIntervalClear = null,
intervalCount = 0,
set_log = function(text){
$result.prepend($("<li/>").text(text));
},
set_star = function(className){
$(this).closest("li").append(
$("<span/>").addClass(className).text("*")
);
};
$("#call-timeout").on("click",function(e){
//5000ms で timeout する
if(dTimeoutClear){
dTimeoutClear();
}
dTimeoutClear =
$(this).timeout(5000)
.always(function(){
dTimeoutClear = null;
})
.done(function(){
set_log("timeout Finish!");
set_star.call(this,"finish");
})
.fail(function(){
set_log("timeout Cancel");
set_star.call(this,"clear");
}).clear;
});
$("#timeout-cancel").on("click",function(){
//timeout のキャンセル
if(dTimeoutClear){
dTimeoutClear();
set_star.call(this,"clear");
}else{
set_log("not start timeout.");
}
});
$("#call-interval").on("click",function(){
//3000ms で interval する
if(dIntervalClear){
dIntervalClear();
}
dIntervalClear =
$(this).interval(3000)
.progress(function(){
set_log(
"intervalCount["+(intervalCount++)+"]");
set_star.call(this,"progress");
})
.always(function(){
dIntervalClear = null;
})
.fail(function(){
set_log("interval Cancel");
set_star.call(this,"clear");
}).clear;
});
$("#interval-cancel").on("click",function(){
//intervalのキャンセル
if(dIntervalClear){
dIntervalClear();
set_star.call(this,"clear");
}else{
set_log("not start interval.");
}
});
});
})(jQuery);
<h1>jQuery Deferredを用いた setTimeout,setInterval の実装例</h1>
<ul>
<li><a id="call-timeout">timeoutテスト(5s)</a></li>
<li><a id="timeout-cancel">timeout キャンセル</a></li>
<li><a id="call-interval">intervalテスト(3s)</a></li>
<li><a id="interval-cancel">intervl キャンセル</a></li>
</ul>
<ul id="result"></ul>
a[id]{
cursor:pointer;
color:blue;
}
a[id]:hover{
font-weight:bold;
}
.finish{
color:red;
}
.clear{
color:yellow;
}
.progress{
color:green;
}