-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
路过微博,盲写了一个JSONP的,未实测 #1
Comments
|
JSONP(url, {
a: '&b=2&c=3',
b: 3
}); 混眼熟。 |
@zswang 这段代码问题太多了…… |
贴自己的代码有一个好,就是优秀的工程师会指出不足,然后自己能够有所精进。才吃饭的功夫就有两位老师提出了问题,我一个一个来看。 1.这种调用的传参,多数情况下都是传入纯js对象,所以偷了懒。不过总归有隐患,该是检查的。 var JSONP = (url, descriptor) => {
var script = document.createElement('script')
var body = document.getElementsByTagName('body')[0]
var parseParam = (paramObj) => {
var paramStr = '?',
prop = ''
for (prop in paramObj) {
if(paramObj.hasOwnProperty(prop)) {
paramStr += (`${prop}=${paramObj[prop]}&`)
}
}
return paramStr
}
var params = parseParam(descriptor.data)
var index = JSONP.cbs.push(descriptor.callback) - 1
script.src = url + params + `callback=JSONP.cbs[${index}]`
body.appendChild(script)
}
JSONP.cbs = [] 志寸老师看看代码哪里还有改进的空间 |
虽然楼上都写得差不多了,还是贴一下我的吧: const JSONP = (url, jsonpObj) => {
let cbName = "cb" + JSONP.count++
let cbQuery = "JSONP." + cbName
let paramsToQuery = obj => {
let query = '?'
for (let k in obj) {
if (obj.hasOwnProperty(k)) {
query += `${k}=${obj[k]}&`
}
}
return query
}
JSONP[cbName] = data => {
try {
jsonpObj.callback(data)
} finally {
delete JSONP[cbName]
document.body.removeChild(script)
}
}
let queryStr = paramsToQuery(jsonpObj.data) + 'callback=' + cbQuery
let script = document.createElement('script')
script.src = url + encodeURIComponent(queryStr)
document.body.appendChild(script)
}
JSONP.count = 0 应该还要考虑url追加查询参数的情况,懒得写了。 |
这位老师提的两个问题: 1.这段代码是在控制台下写的,对 var JSONP = (url, descriptor) => {
var script = document.createElement('script')
var body = document.getElementsByTagName('body')[0]
var parseParam = (paramObj) => {
var paramStr = '?',
prop = ''
for (prop in paramObj) {
if(paramObj.hasOwnProperty(prop)) {
paramStr += (`${prop}=${encodeURIComponent(paramObj[prop])}&`)
}
}
return paramStr
}
var params = parseParam(descriptor.data)
var index = JSONP.cbs.push(descriptor.callback) - 1
script.src = url + params + 'callback=' + encodeURIComponent(`JSONP.cbs[${index}]`)
body.appendChild(script)
}
JSONP.cbs = [] |
受这位同学的启发,利用闭包移除回调和 var JSONP = (url, descriptor) => {
var script = document.createElement('script')
var body = document.getElementsByTagName('body')[0]
var parseParam = (paramObj) => {
var paramStr = '?',
prop = ''
for (prop in paramObj) {
if(paramObj.hasOwnProperty(prop)) {
paramStr += (`${prop}=${encodeURIComponent(paramObj[prop])}&`)
}
}
return paramStr
}
var params = parseParam(descriptor.data)
var callback = (data) => {
descriptor.callback(data)
body.removeChild(script)
JSONP.cbs = [...JSONP.cbs.slice(0, index), ...JSONP.cbs.slice(index+1)]
}
var index = JSONP.cbs.push(callback) - 1
script.src = url + params + 'callback=' + encodeURIComponent(`JSONP.cbs[${index}]`)
body.appendChild(script)
}
JSONP.cbs = [] |
对哦,不过也可以delete掉JSONP.cbs[index],这样索引的位置不会改变。 var JSONP = (url, descriptor) => {
var script = document.createElement('script')
var body = document.getElementsByTagName('body')[0]
var parseParam = (paramObj) => {
var paramStr = '?',
prop = ''
for (prop in paramObj) {
if(paramObj.hasOwnProperty(prop)) {
paramStr += (`${prop}=${encodeURIComponent(paramObj[prop])}&`)
}
}
return paramStr
}
var params = parseParam(descriptor.data)
var callback = (data) => {
descriptor.callback(data)
body.removeChild(script)
delete JSONP.cbs[index]
}
var index = JSONP.cbs.push(callback) - 1
script.src = url + params + 'callback=' + encodeURIComponent(`JSONP.cbs[${index}]`)
body.appendChild(script)
}
JSONP.cbs = [] |
写了一个 @island205 function jsonP(url, settings) {
'use strict';
return new Promise((resolve, reject) => {
let callbackId = -1;
const jsonpCallback = settings.callback;
if (!jsonP.seed) {
callbackId = jsonP.seed = 1;
} else {
callbackId = ++jsonP.seed;
}
if (!jsonP.callbacks) {
jsonP.callbacks = {};
}
const callbackName = `callback_${callbackId}`
jsonP.callbacks[callbackName] = function (data) {
jsonpCallback && jsonpCallback(data);
jsonP.callbacks[callbackName].data = data;
jsonP.callbacks[callbackName].isCalled = true;
}
const data = Object.assign({}, { jsoncallback: `jsonP.callbacks.${callbackName}` }, settings.data || {});
const params = Object.keys(data).map((k) => {
const value = data[k];
if (value || (typeof value === 'number' && value === value) || value === '') {
return `${encodeURIComponent(k)}=${encodeURIComponent(value)}`
} else {
return `${encodeURIComponent(k)}`;
}
}).join('&');
url = url + (url.indexOf('?') !== -1 ? '&' : '?') + params;
function jsonpReq(url) {
const script = document.createElement('script');
script.src = url;
script.async = true;
function cb(e) {
const handle = jsonP.callbacks[callbackName]
if (e.type === 'load' && handle.isCalled) {
resolve(handle.data);
} else {
reject('error');
}
delete jsonP.callbacks[callbackName];
document.body.removeChild(script);
console.log(jsonP.callbacks);
}
script.addEventListener('load', cb, false);
script.addEventListener('error', cb, false);
document.body.appendChild(script);
}
jsonpReq(url);
});
} |
@xlitter 我还看不出有什么问题,👍 看来要写测试用例了。 |
@island205 用timestamp这种方式来标记回调函数如何?
|
@GoBrianGo 不确定,从原理上看无法保证两个 |
@island205 也是,还是用对象来索引比较靠谱。 |
看到各位的代码,让我受教了很多。一个小小的jsonp能涉及很多基础细节。平时只忙着赶项目,研究各种新框架,忽略了基础的重要,是得花时间巩固一下了。 |
The text was updated successfully, but these errors were encountered: