細かすぎて伝わらないjQuery拡張 (23) “$.timing” – Advent Calendar 2016
この記事は賞味期限切れです。(更新から1年が経過しています)
$.timing は、User Timing API のラッパーです。 わずかな機能だけですが、非対応環境に擬似的に対応してみました。
User Timing API とは
User Timing APIは、Webページ上のパフォーマンスを計測するためのインターフェースです。 その役割と使い方は下記URLのエントリーで解説されています。
ものすごくざっくりと使い方を紹介すると、こんな感じ。
- mark() を使って任意のタイミングでタイムスタンプを「マーク」として記録
- measure() を使って、記録したマーク間の所要時間を計測
- タイムスタンプは1/1000ミリ秒という高精度で記録される
執筆時点でのメジャーどころの対応状況は IE10+ / Edge / Firefox / Chrome / Opera 40+ となっていて、 IE9以前やSafari(iOS含)は非対応です。
$.timing
使い方
// マークを記録
$.timing.mark("foo");
$.timing.mark("bar");
// マーク間の所要時間を記録
$.timing.measure("from_foo_to_bar", "foo", "bar");
// 名前からタイムスタンプを取得
$.timing.get("from_foo_to_bar"); // => number
// 記録したマークを全て取得
$.timing.marks(); // => object
// 記録したメジャーを全て取得
$.timing.measures(); // => object
- .mark(name) でそのタイミングのタイムスタンプを記録します
- .measure(name, start, end) で、開始マークから終了マークまでの所要時間を記録します
- .get(name) で名前からマーク・メジャーの時間を数値で取得します
- .marks() / .measures() で記録したマーク・メジャーを全てオブジェクトで取得
Polyfill とは呼べないモノ
$.timing はほんの一部の機能しか実装していません。 また、擬似的に再現してみたとはいえ1/1000ミリ秒単位で計測はちょっと出来無さそうで、 Polyfillと呼ぶにはあまりに片手落ちですね。
core-js あたりでPolyfillを書いているかも?と思いましたが、 中の人が「無理デス」 とおっしゃっています。
Thanks for proposal, but it can’t be polyfilled – only little part and with serious limitations.
https://github.com/zloirock/core-js/issues/130
コード
$.timing = {
_supported: ("performance" in window) && ("timing" in window.performance),
_data: {},
_start: (new Date()).getTime(),
mark: function(name){
if(this._supported){
window.performance.mark(name);
} else {
this._data[name] = {
type: "mark",
startTime: (new Date()).getTime() - this._start
};
}
},
marks: function(){
return this.getEntries("mark", "startTime");
},
measure: function(name, start, end){
if(this._supported){
window.performance.measure(name, start, end);
} else {
this._data[name] = {
type: "measure",
duration: this.get(end) - this.get(start)
};
}
},
measures: function(){
return this.getEntries("measure", "duration");
},
get: function(name){
if(this._supported){
var items = window.performance.getEntriesByName(name);
return items.length ? items[0].startTime : void 0;
}
return (name in this._data) ? this._data[name].startTime : void 0;
},
getEntries: function(type, key){
var data = {};
if(this._supported){
window.performance.getEntriesByType(type)
.forEach(function(item){
data[item.name] = item[key];
});
} else {
$.each(this._data, function(name, item){
if(item.type === type){
data[name] = item[key];
}
});
}
return data;
}
};
コメント