Skip to content

Instantly share code, notes, and snippets.

@kyungw00k
Last active November 7, 2016 10:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kyungw00k/046c7f739d7e8ae73b82c5926dfff989 to your computer and use it in GitHub Desktop.
Save kyungw00k/046c7f739d7e8ae73b82c5926dfff989 to your computer and use it in GitHub Desktop.
handle onload/onfail callback on script tag
function loadScript (src, cb) {
var userAgent = navigator.userAgent.toLowerCase()
var isIE = (userAgent.indexOf('msie') !== -1) ? parseInt(userAgent.split('msie')[1], 10) : false
var doc = document
var tag = 'script'
var el = doc.createElement(tag)
el.done = false
el.async = true
el.charset = 'utf-8'
if (isIE && isIE < 9) {
el.onreadystatechange = function () { // use readyState for handling onload/onfail
if (!el.done && /loaded|complete/.test(this.readyState)) {
_handleIE()
}
}
}
el.onload = function () {
_handleOnload()
}
el.onerror = function (err) {
_handleOnError(err || new Error('failed load: ' + src))
}
el.src = src
if (!isIE || isIE >= 9) { // non-IE or IE 9 above browser can request src when it comes to append to document
_appendTo(document.head || document.getElementsByTagName('head')[0])
}
// use code from http://stackoverflow.com/a/18840568
function _handleIE () {
if (el.readyState === 'complete') {
_appendTo(document.head || document.getElementsByTagName('head')[0])
el.onreadystatechange = null
_handleOnload()
return
}
var firstState = el.readyState
// hack: calling 'children' property changes node's readyState from 'loaded' to complete
// (if script was loaded normally) or to 'loading' - if error detected
el.children
// error detected
if (el.readyState === 'loading' && firstState === 'loaded') {
// custom error code
_handleOnError(new Error('failed load: ' + src))
}
}
function _handleOnload () {
el.done = true
cb()
_destroyTag()
}
function _handleOnError (err) {
cb(err)
_destroyTag()
}
function _destroyTag () {
// Handle memory leak in IE
el.onreadystatechange = null
el.onload = null
el.onerror = null
el.parentNode.removeChild(el)
}
function _appendTo (base) {
base.appendChild(el)
}
}
if (typeof module === 'object' && module.exports) {
module.exports = loadScript
} else {
exports.loadScript = loadScript
}
/* global describe, it, require */
var assert = require('assert')
var loadScript = require('./load-script')
describe('loadScript', function () {
it('should be failed', function (done) {
this.timeout(5 * 1000)
loadScript('http://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.x/jquery.min.js', function (err) {
if (err) {
assert.notEqual(err, null)
done()
}
})
})
it('should be loaded', function (done) {
this.timeout(5 * 1000)
loadScript('http://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js', function (err) {
if (err) {
done(err)
return
}
assert.notEqual(window.jQuery, null)
done()
})
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment