Skip to content

Commit 77b2b77

Browse files
author
a-jie
committed
update v1.0.0
update v1.0.0
1 parent d01e6cf commit 77b2b77

File tree

4 files changed

+217
-0
lines changed

4 files changed

+217
-0
lines changed

lib/index.js

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
;
2+
(function () {
3+
'use strict';
4+
5+
const fetchBak = window.fetch
6+
let index = 0
7+
8+
window.fetch = function (reqOrUrl, options) {
9+
const method = getValFromOpt(options, 'method', '')
10+
11+
if (method.toLowerCase() == 'jsonp') {
12+
return jsonp(reqOrUrl, options)
13+
} else {
14+
return fetchBak.apply(window, arguments)
15+
}
16+
}
17+
18+
////////////////////////////////////////////////////////////////////////////
19+
//
20+
// jsonp func
21+
//
22+
////////////////////////////////////////////////////////////////////////////
23+
function jsonp(reqOrUrl, options) {
24+
if (!reqOrUrl) {
25+
printfError("1 argument required, but only 0 present")
26+
return null
27+
}
28+
29+
return new Promise((resolve, reject) => {
30+
// create cache data
31+
const id = generateId()
32+
const timeout = getValFromOpt(options, 'callback', 8000) << 0
33+
const callback = getValFromOpt(options, 'callback') || getValFromOpt(options, 'cb') || 'callback'
34+
const callbackName = getValFromOpt(options, 'callbackName', id)
35+
const tid = setTimeout(()=>{destroy(', it is timeout')}, timeout)
36+
37+
// generate url
38+
let url = typeof reqOrUrl === 'object' ? reqOrUrl.url : reqOrUrl + ''
39+
url += (url.indexOf('?') > 0 ? '&' : '?').replace('?&', '?')
40+
url += callback + '=' + callbackName
41+
42+
// create script tag
43+
const head = document.getElementsByTagName('head')[0] || document.head
44+
const script = document.createElement('script')
45+
script.src = url
46+
script.onerror = destroy
47+
head.appendChild(script)
48+
49+
window[callbackName] = (res) => {
50+
resolve(new Response(res, url))
51+
destroy()
52+
}
53+
54+
// destroy func
55+
function destroy(msg) {
56+
try {
57+
deleteFromWin(callbackName)
58+
script.parentNode.removeChild(script)
59+
clearTimeout(tid)
60+
} catch (e) { }
61+
62+
reject(new Error(`JSONP request to ${url}${msg || ''}`))
63+
}
64+
})
65+
}
66+
67+
////////////////////////////////////////////////////////////////////////////
68+
//
69+
// Response
70+
//
71+
////////////////////////////////////////////////////////////////////////////
72+
function Response(res, url) {
73+
this.ok = true
74+
this.status = 200
75+
this.type = 'default'
76+
this.url = url || ''
77+
this.statusText = 'OK'
78+
this.bodyUsed = false
79+
this._bodyText = res
80+
}
81+
82+
Response.prototype = {
83+
text: function () {
84+
this.bodyUsed = true
85+
return Promise.resolve(this._bodyText)
86+
},
87+
88+
json: function () {
89+
this.bodyUsed = true
90+
return Promise.resolve(toJson(this._bodyText))
91+
},
92+
93+
clone: function () {
94+
return new Response(this._bodyText, url)
95+
}
96+
}
97+
98+
////////////////////////////////////////////////////////////////////////////
99+
//
100+
// generate Id
101+
//
102+
////////////////////////////////////////////////////////////////////////////
103+
function generateId() {
104+
return `jsonpcallback_${~~(Math.random() * Math.pow(10, 7))}_${++index}`
105+
}
106+
107+
////////////////////////////////////////////////////////////////////////////
108+
//
109+
// delete window custom props
110+
//
111+
////////////////////////////////////////////////////////////////////////////
112+
function deleteFromWin(key) {
113+
try {
114+
delete window[key]
115+
} catch (e) { window[key] = undefined }
116+
}
117+
118+
////////////////////////////////////////////////////////////////////////////
119+
//
120+
// get value from options
121+
//
122+
////////////////////////////////////////////////////////////////////////////
123+
function getValFromOpt(options, key, defaultVal) {
124+
defaultVal = defaultVal !== undefined ? defaultVal : null;
125+
if (options && typeof options === 'object') return options[key] !== undefined ? options[key] : defaultVal;
126+
return defaultVal;
127+
}
128+
129+
130+
////////////////////////////////////////////////////////////////////////////
131+
//
132+
// convert to json data
133+
//
134+
////////////////////////////////////////////////////////////////////////////
135+
function toJson(res) {
136+
if (typeof ref === 'string') {
137+
try {
138+
return JSON.parse(res)
139+
} catch (e) {
140+
return eval(`(${res})`)
141+
} finally {
142+
return res
143+
}
144+
} else {
145+
return res
146+
}
147+
}
148+
149+
function printfError() {
150+
window.console && console.error.apply(console, arguments)
151+
}
152+
153+
})();

package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "fetch-jsonp-polyfill",
3+
"version": "1.0.0",
4+
"description": "a jsonp fetch polyfill",
5+
"main": "bin/index.js",
6+
"directories": {
7+
"test": "test"
8+
},
9+
"scripts": {
10+
"test": "jest"
11+
},
12+
"keywords": [
13+
"fetch",
14+
"jsonp"
15+
],
16+
"author": "a-jie",
17+
"license": "ISC",
18+
"devDependencies": {
19+
"jest": "^22.3.0"
20+
}
21+
}

test/test.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script src="../libs/index.js"></script>
2+
3+
<script>
4+
var URL = 'http://jsfiddle.net/echo/jsonp/';
5+
6+
fetch(URL, {
7+
method: "JSONP"
8+
})
9+
.then(response => response.json())
10+
.then(res => {
11+
console.log(res)
12+
if (res.ok) {
13+
console.log(res.json());
14+
}
15+
16+
// expect(res.json()).toBe(3);
17+
})
18+
.catch(err => {
19+
console.log(err);
20+
});
21+
</script>

test/test.spec.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
require('../libs/index.js');
2+
3+
var URL = 'http://jsfiddle.net/echo/jsonp/';
4+
5+
test('test jsonp fetch', () => {
6+
fetch(URL, {
7+
//method: "JSONP"
8+
}).then(res => {
9+
console.log(res);
10+
expect(res.json()).toBe(3);
11+
});
12+
})
13+
14+
// test('test jsonp callbackName', () => {
15+
// fetch(URL, {
16+
// method: "JSONP",
17+
// callbackName: "hello_fetch_jsonp"
18+
// }).then(res => {
19+
// console.log(res);
20+
// expect(res.json()).toBe(3);
21+
// });
22+
// })

0 commit comments

Comments
 (0)