Last active
August 25, 2018 06:21
-
-
Save kamataryo/797630c0f47f7ce88cedd099d72a1ab8 to your computer and use it in GitHub Desktop.
Add snippet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* タイムアウト機能を埋め込むプロキシ | |
* targetが一定時間呼ばれなかったら固有の処理を実行する | |
* タイムアウトすると、呼ばれた回数のカウンタはリセットされる | |
* @param {function} target プロキシされる関数 | |
* @param {{timeout: number, callback: function}} opts オプション | |
* @return {function} プロキシされた関数 | |
*/ | |
const timeoutProxy = (target, opts) => { | |
/** | |
* タイムアウトに関する情報を元の関数に埋め込む | |
* @type {symbol} | |
*/ | |
const _timeoutTag = Symbol('timeout tag') | |
return new Proxy(target, { | |
/** | |
* apply handler | |
* @param {function} target ターゲット | |
* @param {any} thisArg コンテキスト | |
* @param {array} argumentList 引数 | |
* @return {any} 元の関数の戻り値 | |
*/ | |
apply: (target, thisArg, argumentList) => { | |
const timeoutParams = target[_timeoutTag] | |
if (!timeoutParams) { | |
// 初めて関数が呼ばれた | |
const timerId = setTimeout(() => { | |
clearTimeout(timerId) | |
opts.callback(target[_timeoutTag].count, opts.timeout, target) | |
target[_timeoutTag] = void 0 | |
}, opts.timeout) | |
target[_timeoutTag] = { | |
called: true, | |
count: 0, | |
timerId, | |
} | |
} else { | |
// 2回目以降に関数が呼ばれた | |
const { timerId } = target[_timeoutTag] | |
clearTimeout(timerId) | |
target[_timeoutTag].timerId = setTimeout(() => { | |
clearTimeout(timerId) | |
const { count } = target[_timeoutTag] | |
opts.callback(count, opts.timeout, target) | |
target[_timeoutTag] = void 0 | |
}, opts.timeout) | |
} | |
target[_timeoutTag].count++ | |
return target(argumentList) | |
}, | |
}) | |
} | |
// サンプルの関数 | |
const sample = () => console.log('hello') | |
const opts = { | |
timeout: 1000, | |
callback: (count, timeout, target) => | |
console.log( | |
`タイムアウト(${timeout}ミリ秒)するまでに ${count} 回 ${ | |
target.name | |
} が呼ばれました`, | |
), | |
} | |
// プロキシを使って振る舞いを改ざんした新しい関数を作る | |
const timeoutFunc = timeoutProxy(sample, opts) | |
timeoutFunc() | |
timeoutFunc() | |
timeoutFunc() | |
timeoutFunc() | |
setTimeout(timeoutFunc, 500) | |
setTimeout(timeoutFunc, 3500) | |
// $ node ./timeout2.js | |
// hello | |
// hello | |
// hello | |
// hello | |
// hello | |
// タイムアウト(1000ミリ秒)するまでに 5 回 sample が呼ばれました | |
// hello | |
// タイムアウト(1000ミリ秒)するまでに 1 回 sample が呼ばれました |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment