Modern Chrome and Opera fully support the HTML 5 draft spec for ErrorEvent and window.onerror. In both of these browsers you can either use window.onerror, or bind to the 'error' event properly:
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.log(message, "from", error.stack);
// You can send data to your server
// sendError(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.log(e.error.message, "from", e.error.stack);
// You can send data to your server
// sendError(data);
})
Unfortunately Firefox, Safari and IE are still around and we have to support them too. As the stacktrace is not available in window.onerror we have to do a little bit more work.
It turns out that the only thing we can do to get stacktraces from errors is to wrap all of our code in a try{ }catch(e){ } block and then look at e.stack. We can make the process somewhat easier with a function called wrap that takes a function and returns a new function with good error handling.
function wrap(func) {
// Ensure we only wrap the function once.
if (!func._wrapped) {
func._wrapped = function () {
try{
func.apply(this, arguments);
} catch(e) {
console.log(e.message, "from", e.stack);
// You can send data to your server
// sendError(data);
throw e;
}
}
}
return func._wrapped;
};
This works. Any function that you wrap manually will have good error handling, but it turns out that we can actually do it for you automatically in most cases.
By changing the global definition of addEventListener so that it automatically wraps the callback we can automatically insert try{ }catch(e){ } around most code. This lets existing code continue to work, but adds high-quality exception tracking.
var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
addEventListener.call(this, event, wrap(callback), bubble);
}
We also need to make sure that removeEventListener keeps working. At the moment it won't because the argument to addEventListener is changed. Again we only need to fix this on the prototype object:
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
Transmit error data to your backend
You can send error data using image tag as follows
function sendError(data) {
var img = newImage(),
src = 'http://yourserver.com/jserror&data=' + encodeURIComponent(JSON.stringify(data));
img.crossOrigin = 'anonymous';
img.onload = function success() {
console.log('success', data);
};
img.onerror = img.onabort = function failure() {
console.error('failure', data);
};
img.src = src;
}
вторник, 29 марта 2016 г.
среда, 16 марта 2016 г.
Support ECMAScript 5, 6, 7 Shims and Shams
ECMAScript 5 (есть в es5-shim)
Object
- Object.keys
Array
- Array.isArray
- [].indexOf
- [].lastIndexOf
- [].every
- [].some
- [].forEach
- [].map
- [].filter
- [].reduce
- [].reduceRight
String
- "".trim
- "".split - crossbrowser (нет в es5-shim)
Function
- (function(){}).bind
Date
- Date.now
- (new Date()).toISOString
- (new Date()).toJSON
- (new Date()).parse -> return NaN for invalid dates
JSON (нет в es5-shim)
- JSON.parse
- JSON.stringify
ECMAScript 6 (есть в es6-shim)
Object
- Object.assign
- Object.is
Только, если есть поддержка ES5
- Object.getPrototypeOf
- Object.getOwnPropertyDescriptor
- Object.getOwnPropertyNames
- Object.seal
- Object.freeze
- Object.preventExtensions
- Object.isSealed
- Object.isExtensible
- Object.keys
String
- String.raw
- String.fromCodePoint
- "".codePointAt
- "".repeat
- "".startsWith
- "".endsWith
- "".includes
Number
- Number.isFinite
- Number.isInteger
- Number.isSafeInteger
- Number.isNaN
- Number.EPSILON
- Number.MIN_SAFE_INTEGER
- Number.MAX_SAFE_INTEGER
- Number('0o1')
- Number('0b1')
Array
- Array.from
- Array.of
- [].copyWithin
- [].find
- [].fineIndex
- [].fill
- [].keys
- [].values
- [].entries
RegExp
- (//).flags
Math
- Math.clz32
- Math.imul
- Math.sign
- Math.log10
- Math.log2
- Math.log1p
- Math.expm1
- Math.cosh
- Math.sinh
- Math.acosh
- Math.asinh
- Math.atanh
- Math.trunc
- Math.fround
- Math.cbrt
- Math.hypot
Map
Set
Reflect
Promise
ECMAScript 7 (есть в es7-shim)
Object
- Object.values
- Object.entries
- Object.getOwnPropertyDescriptors
Array
- [].includes
String
- "".padStart
- "".padEnd
- "".trimLeft
- "".trimRight
- "".at
Map
- (new Map()).toJSON
Set
- (new Set()).toJSON
Последовательность включения новых функций в проект:
- es5-shim.min.js
- es5-sham.min.js
- json3.min.js
- es6-shim.min.js
- es6-sham.min.js
- es7-shim.min.js
...other-libs.js...
Object
- Object.keys
Array
- Array.isArray
- [].indexOf
- [].lastIndexOf
- [].every
- [].some
- [].forEach
- [].map
- [].filter
- [].reduce
- [].reduceRight
String
- "".trim
- "".split - crossbrowser (нет в es5-shim)
Function
- (function(){}).bind
Date
- Date.now
- (new Date()).toISOString
- (new Date()).toJSON
- (new Date()).parse -> return NaN for invalid dates
JSON (нет в es5-shim)
- JSON.parse
- JSON.stringify
ECMAScript 6 (есть в es6-shim)
Object
- Object.assign
- Object.is
Только, если есть поддержка ES5
- Object.getPrototypeOf
- Object.getOwnPropertyDescriptor
- Object.getOwnPropertyNames
- Object.seal
- Object.freeze
- Object.preventExtensions
- Object.isSealed
- Object.isExtensible
- Object.keys
String
- String.raw
- String.fromCodePoint
- "".codePointAt
- "".repeat
- "".startsWith
- "".endsWith
- "".includes
Number
- Number.isFinite
- Number.isInteger
- Number.isSafeInteger
- Number.isNaN
- Number.EPSILON
- Number.MIN_SAFE_INTEGER
- Number.MAX_SAFE_INTEGER
- Number('0o1')
- Number('0b1')
Array
- Array.from
- Array.of
- [].copyWithin
- [].find
- [].fineIndex
- [].fill
- [].keys
- [].values
- [].entries
RegExp
- (//).flags
Math
- Math.clz32
- Math.imul
- Math.sign
- Math.log10
- Math.log2
- Math.log1p
- Math.expm1
- Math.cosh
- Math.sinh
- Math.acosh
- Math.asinh
- Math.atanh
- Math.trunc
- Math.fround
- Math.cbrt
- Math.hypot
Map
Set
Reflect
Promise
ECMAScript 7 (есть в es7-shim)
Object
- Object.values
- Object.entries
- Object.getOwnPropertyDescriptors
Array
- [].includes
String
- "".padStart
- "".padEnd
- "".trimLeft
- "".trimRight
- "".at
Map
- (new Map()).toJSON
Set
- (new Set()).toJSON
Последовательность включения новых функций в проект:
- es5-shim.min.js
- es5-sham.min.js
- json3.min.js
- es6-shim.min.js
- es6-sham.min.js
- es7-shim.min.js
...other-libs.js...
понедельник, 14 марта 2016 г.
JavaScript Decorator
function decorate (baseFunction, decoratorFunction) {
return function () {decoratorFunction(baseFunction, arguments);};
}
function a (a) {
console.log(a);
return 'OK';
}
function b (baseFunction, baseFunctionArguments) {
console.log('start');
baseFunction.apply(null, baseFunctionArguments);
console.log('b');
console.log('stop');
}
a = decorate(a, b);
a('a');
function trace (baseFunction, baseFunctionArguments) {
var result = baseFunction.apply(null, baseFunctionArguments);
console.log('TRACE: ' + baseFunction.name + ' (' + Array.prototype.slice.call(baseFunctionArguments).join(', ') + ') => ' + result);
return result;
}
var c = decorate(a, trace);
c('a', 'b', 1, 2, {});
return function () {decoratorFunction(baseFunction, arguments);};
}
function a (a) {
console.log(a);
return 'OK';
}
function b (baseFunction, baseFunctionArguments) {
console.log('start');
baseFunction.apply(null, baseFunctionArguments);
console.log('b');
console.log('stop');
}
a = decorate(a, b);
a('a');
function trace (baseFunction, baseFunctionArguments) {
var result = baseFunction.apply(null, baseFunctionArguments);
console.log('TRACE: ' + baseFunction.name + ' (' + Array.prototype.slice.call(baseFunctionArguments).join(', ') + ') => ' + result);
return result;
}
var c = decorate(a, trace);
c('a', 'b', 1, 2, {});
Подписаться на:
Сообщения (Atom)