Skip to content

Commit 3140e2e

Browse files
authored
Merge pull request #6 from LancerComet/feature/complex-object
+ Add complex querying support.
2 parents 37ec3a3 + e4eb851 commit 3140e2e

File tree

5 files changed

+243
-104
lines changed

5 files changed

+243
-104
lines changed

dist/vue-jsonp.umd.js

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
/**
1111
* Vue Jsonp By LancerComet at 16:35, 2016.10.17.
1212
* # Carry Your World #
13-
*
13+
*
1414
* @author: LancerComet
1515
* @license: MIT
1616
*/
@@ -33,7 +33,7 @@ var vueJsonp = {
3333
* @param { String } url Target URL address.
3434
* @param { Object } params Querying params object.
3535
* @param { Number } timeout Timeout setting (ms).
36-
*
36+
*
3737
* @example
3838
* Vue.jsonp('/url', {
3939
* callbackQuery: ''
@@ -47,7 +47,7 @@ function jsonp (url, params, timeout) {
4747
timeout = timeout || _timeout
4848

4949
return new Promise(function (resolve, reject) {
50-
if (Object.prototype.toString.call(url) !== '[object String]') {
50+
if (typeof url !== 'string') {
5151
throw new Error('[Vue.jsonp] Type of param "url" is not string.')
5252
}
5353

@@ -61,25 +61,30 @@ function jsonp (url, params, timeout) {
6161
delete params.callbackName
6262

6363
// Convert params to querying str.
64-
var queryStr = formatParams(params)
64+
var queryStrs = []
65+
Object.keys(params).forEach(function (queryName) {
66+
queryStrs = queryStrs.concat(formatParams(queryName, params[queryName]))
67+
})
68+
69+
var queryStr = flatten(queryStrs).join('&')
6570

6671
// Timeout timer.
6772
var timeoutTimer = null
68-
73+
6974
// Setup timeout.
7075
if (typeof timeout === 'number') {
7176
timeoutTimer = setTimeout(function () {
72-
removeErrorListener()
77+
removeErrorListener()
7378
headNode.removeChild(paddingScript)
7479
delete window[callbackName]
7580
reject({ statusText: 'Request Timeout', status: 408 })
7681
}, timeout)
7782
}
78-
83+
7984
// Create global function.
8085
window[callbackName] = function (json) {
8186
clearTimeout(timeoutTimer)
82-
removeErrorListener()
87+
removeErrorListener()
8388
headNode.removeChild(paddingScript)
8489
resolve(json)
8590
delete window[callbackName]
@@ -129,15 +134,53 @@ function randomStr () {
129134

130135
/**
131136
* Format params into querying string.
132-
* @param { Object }
133-
* @return { String }
137+
* @param {{}}
138+
* @return {string[]}
134139
*/
135-
function formatParams (param) {
136-
var arr = []
137-
Object.keys(param).forEach(function (name) {
138-
arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(param[name]))
140+
function formatParams (queryName, value) {
141+
queryName = queryName.replace(/=/g, '')
142+
var result = []
143+
144+
switch (value.constructor) {
145+
case String:
146+
case Number:
147+
case Boolean:
148+
result.push(encodeURIComponent(queryName) + '=' + encodeURIComponent(value))
149+
break
150+
151+
case Array:
152+
value.forEach(function (item) {
153+
result = result.concat(formatParams(queryName + '[]=', item))
154+
})
155+
break
156+
157+
case Object:
158+
Object.keys(value).forEach(function (key) {
159+
var item = value[key]
160+
result = result.concat(formatParams(queryName + '[' + key + ']', item))
161+
})
162+
break
163+
}
164+
165+
return result
166+
}
167+
168+
/**
169+
* Flat querys.
170+
*
171+
* @param {any} array
172+
* @returns
173+
*/
174+
function flatten (array) {
175+
var querys = []
176+
array.forEach(function (item) {
177+
if (typeof item === 'string') {
178+
querys.push(item)
179+
} else {
180+
querys = querys.concat(flatten(item))
181+
}
139182
})
140-
return arr.join('&')
183+
return querys
141184
}
142185

143186
return vueJsonp;

src/index.js

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Vue Jsonp By LancerComet at 16:35, 2016.10.17.
33
* # Carry Your World #
4-
*
4+
*
55
* @author: LancerComet
66
* @license: MIT
77
*/
@@ -24,7 +24,7 @@ var vueJsonp = {
2424
* @param { String } url Target URL address.
2525
* @param { Object } params Querying params object.
2626
* @param { Number } timeout Timeout setting (ms).
27-
*
27+
*
2828
* @example
2929
* Vue.jsonp('/url', {
3030
* callbackQuery: ''
@@ -38,7 +38,7 @@ function jsonp (url, params, timeout) {
3838
timeout = timeout || _timeout
3939

4040
return new Promise(function (resolve, reject) {
41-
if (Object.prototype.toString.call(url) !== '[object String]') {
41+
if (typeof url !== 'string') {
4242
throw new Error('[Vue.jsonp] Type of param "url" is not string.')
4343
}
4444

@@ -52,25 +52,30 @@ function jsonp (url, params, timeout) {
5252
delete params.callbackName
5353

5454
// Convert params to querying str.
55-
var queryStr = formatParams(params)
55+
var queryStrs = []
56+
Object.keys(params).forEach(function (queryName) {
57+
queryStrs = queryStrs.concat(formatParams(queryName, params[queryName]))
58+
})
59+
60+
var queryStr = flatten(queryStrs).join('&')
5661

5762
// Timeout timer.
5863
var timeoutTimer = null
59-
64+
6065
// Setup timeout.
6166
if (typeof timeout === 'number') {
6267
timeoutTimer = setTimeout(function () {
63-
removeErrorListener()
68+
removeErrorListener()
6469
headNode.removeChild(paddingScript)
6570
delete window[callbackName]
6671
reject({ statusText: 'Request Timeout', status: 408 })
6772
}, timeout)
6873
}
69-
74+
7075
// Create global function.
7176
window[callbackName] = function (json) {
7277
clearTimeout(timeoutTimer)
73-
removeErrorListener()
78+
removeErrorListener()
7479
headNode.removeChild(paddingScript)
7580
resolve(json)
7681
delete window[callbackName]
@@ -120,13 +125,51 @@ function randomStr () {
120125

121126
/**
122127
* Format params into querying string.
123-
* @param { Object }
124-
* @return { String }
128+
* @param {{}}
129+
* @return {string[]}
125130
*/
126-
function formatParams (param) {
127-
var arr = []
128-
Object.keys(param).forEach(function (name) {
129-
arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(param[name]))
131+
function formatParams (queryName, value) {
132+
queryName = queryName.replace(/=/g, '')
133+
var result = []
134+
135+
switch (value.constructor) {
136+
case String:
137+
case Number:
138+
case Boolean:
139+
result.push(encodeURIComponent(queryName) + '=' + encodeURIComponent(value))
140+
break
141+
142+
case Array:
143+
value.forEach(function (item) {
144+
result = result.concat(formatParams(queryName + '[]=', item))
145+
})
146+
break
147+
148+
case Object:
149+
Object.keys(value).forEach(function (key) {
150+
var item = value[key]
151+
result = result.concat(formatParams(queryName + '[' + key + ']', item))
152+
})
153+
break
154+
}
155+
156+
return result
157+
}
158+
159+
/**
160+
* Flat querys.
161+
*
162+
* @param {any} array
163+
* @returns
164+
*/
165+
function flatten (array) {
166+
var querys = []
167+
array.forEach(function (item) {
168+
if (typeof item === 'string') {
169+
querys.push(item)
170+
} else {
171+
querys = querys.concat(flatten(item))
172+
}
130173
})
131-
return arr.join('&')
174+
return querys
132175
}

test/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
Function.prototype.bind = require('function-bind')
44

55
// require all test files (files that ends with .spec.js)
6+
require('./specs/format-params.spec.js')
67
require('./specs/vue-jsonp.spec.js')

test/specs/format-params.spec.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
describe('Param format testing.', function () {
2+
it('Should format params correctly - simple.', function () {
3+
var dateNow = Date.now()
4+
var result = createQueryStr({
5+
callbackQuery: 'callback',
6+
callbackName: 'func',
7+
date: dateNow
8+
})
9+
10+
var expected = 'callbackQuery=callback&callbackName=func&date=' + dateNow
11+
expect(decodeURIComponent(result)).equal(expected)
12+
})
13+
14+
it('Should format params correctly - complex.', function () {
15+
var result = createQueryStr({
16+
callbackQuery: 'callback',
17+
callbackName: 'func',
18+
source: 'testing',
19+
info: {
20+
name: 'LancerComet',
21+
age: 27,
22+
address: ['Beijing', 'NewYork'],
23+
score: {
24+
math: 10,
25+
english: 100,
26+
},
27+
something: {
28+
one: [1, 2, { wow: true }],
29+
two: {
30+
wow: false,
31+
three: [1, 2, 3]
32+
}
33+
}
34+
}
35+
})
36+
37+
var expected = 'callbackQuery=callback&callbackName=func&source=testing&info[name]=LancerComet&info[age]=27&info[address][]=Beijing&info[address][]=NewYork&info[score][math]=10&info[score][english]=100&info[something][one][]=1&info[something][one][]=2&info[something][one][][wow]=true&info[something][two][wow]=false&info[something][two][three][]=1&info[something][two][three][]=2&info[something][two][three][]=3'
38+
39+
expect(decodeURIComponent(result)).equal(expected)
40+
})
41+
})
42+
43+
function createQueryStr (param) {
44+
var querys = []
45+
Object.keys(param).forEach(function (keyName) {
46+
querys.push(formatParams(keyName, param[keyName]))
47+
})
48+
return flatten(querys).join('&')
49+
}
50+
51+
/**
52+
* Format params into querying string.
53+
* @param {{}}
54+
* @return {string[]}
55+
*/
56+
function formatParams (queryName, value) {
57+
queryName = queryName.replace(/=/g, '')
58+
var result = []
59+
60+
switch (value.constructor) {
61+
case String:
62+
case Number:
63+
case Boolean:
64+
result.push(encodeURIComponent(queryName) + '=' + encodeURIComponent(value))
65+
break
66+
67+
case Array:
68+
value.forEach(function (item) {
69+
result = result.concat(formatParams(queryName + '[]=', item))
70+
})
71+
break
72+
73+
case Object:
74+
Object.keys(value).forEach(function (key) {
75+
var item = value[key]
76+
result = result.concat(formatParams(queryName + '[' + key + ']', item))
77+
})
78+
break
79+
}
80+
81+
return result
82+
}
83+
84+
/**
85+
* Flat querys.
86+
*
87+
* @param {any} array
88+
* @returns
89+
*/
90+
function flatten (array) {
91+
var querys = []
92+
array.forEach(function (item) {
93+
if (typeof item === 'string') {
94+
querys.push(item)
95+
} else {
96+
querys = querys.concat(flatten(item))
97+
}
98+
})
99+
return querys
100+
}

0 commit comments

Comments
 (0)