taro-sockjs-client
Version:
sockjs-client for Taro
96 lines (86 loc) • 2.31 kB
JavaScript
import random from '../../utils/random'
import urlUtils from '../../utils/url'
import debug from '../../utils/debug'
let form, area
function createIframe(id) {
debug('createIframe', id)
try {
// ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
return global.document.createElement('<iframe name="' + id + '">')
} catch (x) {
let iframe = global.document.createElement('iframe')
iframe.name = id
return iframe
}
}
function createForm() {
debug('createForm')
form = global.document.createElement('form')
form.style.display = 'none'
form.style.position = 'absolute'
form.method = 'POST'
form.enctype = 'application/x-www-form-urlencoded'
form.acceptCharset = 'UTF-8'
area = global.document.createElement('textarea')
area.name = 'd'
form.appendChild(area)
global.document.body.appendChild(form)
}
export default function (url, payload, callback) {
debug(url, payload)
if (!form) {
createForm()
}
let id = 'a' + random.string(8)
form.target = id
form.action = urlUtils.addQuery(
urlUtils.addPath(url, '/jsonp_send'),
'i=' + id,
)
let iframe = createIframe(id)
iframe.id = id
iframe.style.display = 'none'
form.appendChild(iframe)
try {
area.value = payload
} catch (e) {
// seriously broken browsers get here
}
form.submit()
let completed = function (err) {
debug('completed', id, err)
if (!iframe.onerror) {
return
}
iframe.onreadystatechange = iframe.onerror = iframe.onload = null
// Opera mini doesn't like if we GC iframe
// immediately, thus this timeout.
setTimeout(function () {
debug('cleaning up', id)
iframe.parentNode.removeChild(iframe)
iframe = null
}, 500)
area.value = ''
// It is not possible to detect if the iframe succeeded or
// failed to submit our form.
callback(err)
}
iframe.onerror = function () {
debug('onerror', id)
completed()
}
iframe.onload = function () {
debug('onload', id)
completed()
}
iframe.onreadystatechange = function (e) {
debug('onreadystatechange', id, iframe.readyState, e)
if (iframe.readyState === 'complete') {
completed()
}
}
return function () {
debug('aborted', id)
completed(new Error('Aborted'))
}
}