188 lines
4.2 KiB
JavaScript
188 lines
4.2 KiB
JavaScript
;(function(root, factory) {
|
|
if (typeof define === 'function' && define.amd) {
|
|
define([], factory);
|
|
} else if (typeof exports === 'object') {
|
|
module.exports = factory();
|
|
} else {
|
|
root.vueJsonp = factory();
|
|
}
|
|
}(this, function() {
|
|
/**
|
|
* Vue Jsonp By LancerComet at 16:35, 2016.10.17.
|
|
* # Carry Your World #
|
|
*
|
|
* @author: LancerComet
|
|
* @license: MIT
|
|
*/
|
|
|
|
var _timeout = null
|
|
|
|
var vueJsonp = {
|
|
install: function (Vue, options) {
|
|
Vue.jsonp = jsonp
|
|
Vue.prototype.$jsonp = jsonp
|
|
|
|
if (typeof options === 'number') {
|
|
_timeout = options
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* JSONP function.
|
|
* @param { String } url Target URL address.
|
|
* @param { Object } params Querying params object.
|
|
* @param { Number } timeout Timeout setting (ms).
|
|
*
|
|
* @example
|
|
* Vue.jsonp('/url', {
|
|
* callbackQuery: ''
|
|
* callbackName: '',
|
|
* name: 'LancerComet',
|
|
* age: 26
|
|
* }, 1000)
|
|
*/
|
|
function jsonp (url, params, timeout) {
|
|
params = params || {}
|
|
timeout = timeout || _timeout
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
if (typeof url !== 'string') {
|
|
throw new Error('[Vue.jsonp] Type of param "url" is not string.')
|
|
}
|
|
|
|
var callbackQuery = params.callbackQuery || 'callback'
|
|
var callbackName = params.callbackName || 'jsonp_' + randomStr()
|
|
|
|
params[callbackQuery] = callbackName
|
|
|
|
// Remove callbackQuery and callbackName.
|
|
delete params.callbackQuery
|
|
delete params.callbackName
|
|
|
|
// Convert params to querying str.
|
|
var queryStrs = []
|
|
Object.keys(params).forEach(function (queryName) {
|
|
queryStrs = queryStrs.concat(formatParams(queryName, params[queryName]))
|
|
})
|
|
|
|
var queryStr = flatten(queryStrs).join('&')
|
|
|
|
// Timeout timer.
|
|
var timeoutTimer = null
|
|
|
|
// Setup timeout.
|
|
if (typeof timeout === 'number') {
|
|
timeoutTimer = setTimeout(function () {
|
|
removeErrorListener()
|
|
headNode.removeChild(paddingScript)
|
|
delete window[callbackName]
|
|
reject({ statusText: 'Request Timeout', status: 408 })
|
|
}, timeout)
|
|
}
|
|
|
|
// Create global function.
|
|
window[callbackName] = function (json) {
|
|
clearTimeout(timeoutTimer)
|
|
removeErrorListener()
|
|
headNode.removeChild(paddingScript)
|
|
resolve(json)
|
|
delete window[callbackName]
|
|
}
|
|
|
|
// Create script element.
|
|
var headNode = document.querySelector('head')
|
|
var paddingScript = document.createElement('script')
|
|
|
|
// Add error listener.
|
|
paddingScript.addEventListener('error', onError)
|
|
|
|
// Append to head element.
|
|
paddingScript.src = url + (/\?/.test(url) ? '&' : '?') + queryStr
|
|
headNode.appendChild(paddingScript)
|
|
|
|
/**
|
|
* Padding script on-error event.
|
|
* @param {Event} event
|
|
*/
|
|
function onError (event) {
|
|
removeErrorListener()
|
|
clearTimeout(timeoutTimer)
|
|
reject({
|
|
status: 400,
|
|
statusText: 'Bad Request'
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Remove on-error event listener.
|
|
*/
|
|
function removeErrorListener () {
|
|
paddingScript.removeEventListener('error', onError)
|
|
}
|
|
})
|
|
|
|
}
|
|
|
|
/**
|
|
* Generate random string.
|
|
* @return { String }
|
|
*/
|
|
function randomStr () {
|
|
return (Math.floor(Math.random() * 100000) * Date.now()).toString(16)
|
|
}
|
|
|
|
/**
|
|
* Format params into querying string.
|
|
* @param {{}}
|
|
* @return {string[]}
|
|
*/
|
|
function formatParams (queryName, value) {
|
|
queryName = queryName.replace(/=/g, '')
|
|
var result = []
|
|
|
|
switch (value.constructor) {
|
|
case String:
|
|
case Number:
|
|
case Boolean:
|
|
result.push(encodeURIComponent(queryName) + '=' + encodeURIComponent(value))
|
|
break
|
|
|
|
case Array:
|
|
value.forEach(function (item) {
|
|
result = result.concat(formatParams(queryName + '[]=', item))
|
|
})
|
|
break
|
|
|
|
case Object:
|
|
Object.keys(value).forEach(function (key) {
|
|
var item = value[key]
|
|
result = result.concat(formatParams(queryName + '[' + key + ']', item))
|
|
})
|
|
break
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Flat querys.
|
|
*
|
|
* @param {any} array
|
|
* @returns
|
|
*/
|
|
function flatten (array) {
|
|
var querys = []
|
|
array.forEach(function (item) {
|
|
if (typeof item === 'string') {
|
|
querys.push(item)
|
|
} else {
|
|
querys = querys.concat(flatten(item))
|
|
}
|
|
})
|
|
return querys
|
|
}
|
|
|
|
return vueJsonp;
|
|
}));
|