From 1f379af7ac77a1e522ac067537b2dc6b6fb6c205 Mon Sep 17 00:00:00 2001 From: StEve Young <2747745470@qq.com> Date: Mon, 17 Feb 2020 11:40:14 +0800 Subject: [PATCH] fix(jsonp): do not set default callbackName, set default charset (#45) --- docs/config/runtime.md | 30 +++++++++++++++++-- examples/apis-web/fake-get.js | 13 ++++++++- examples/apis-web/index.d.ts | 1 + package.json | 55 +++++++++++++++++------------------ src/exportUtils.js | 4 +-- src/index.js | 24 ++++++++------- src/utils/fp.js | 4 +-- src/utils/params.js | 4 +-- test/__tests__/jsonp.test.js | 21 +++++++++++++ test/__tests__/wx.test.js | 3 +- 10 files changed, 110 insertions(+), 49 deletions(-) diff --git a/docs/config/runtime.md b/docs/config/runtime.md index 5487d06..a689f16 100644 --- a/docs/config/runtime.md +++ b/docs/config/runtime.md @@ -10,16 +10,42 @@ exampleApi.foo( ) ``` +## callback 回调函数参数的名称 +通过 jsonp 发起请求时,在请求的 `url` 上都会有一个参数用来标识回调函数,例如 `callback=jsonp_1581908021389_16566`。 + +`callback` 这个参数可以用来标识等号左边的值(不填则默认为 `callback`)。 + +```js +exampleApi.foo( + { ... }, + { callback: `cb` } +) +``` + +最终的请求 `url` 大概是:`/foo?cb=jsonp_1581908021389_16566`。 + +::: tip +`callback` 其实就是透传了 `fetch-jsonp` 中的 `jsonpCallback`。 +::: + ## callbackName 回调函数名称 -在通过 jsonp 发起请求时,为了使用缓存一般需要添加 callbackName,但是注意重复请求时会报错。 +通过 jsonp 发起请求时,一般默认回调函数的名称都是由一些随机值构成,例如 `callback=jsonp_1581908021389_16566` + +不过为了使用缓存一般需要添加 `callbackName`,但是注意重复请求时会报错(此时不设置 `callbackName` 即可)。 ```js exampleApi.foo( { ... }, - { callbackName: `foo` } + { callbackName: `fooCallback` } ) ``` +最终的请求 `url` 大概是:`/foo?callback=fooCallback`。 + +::: tip +`callbackName` 其实就是透传了 `fetch-jsonp` 中的 `jsonpCallbackFunction`。 +::: + ## 其他参数 公共配置一节中的所有参数(除了 `pathList` 外),以及自身配置一节中的所有参数均有效,且优先级最高。 diff --git a/examples/apis-web/fake-get.js b/examples/apis-web/fake-get.js index bce5879..44f9763 100644 --- a/examples/apis-web/fake-get.js +++ b/examples/apis-web/fake-get.js @@ -9,7 +9,11 @@ export default { commonParams: null, // 透传 `fetch-jsonp` 需要配置的参数。例如需要传递超时时间时可添加: - jsonpOptions: { timeout: 10 * 1000 }, + jsonpOptions: { + timeout: 10 * 1000, + jsonpCallback: 'cb', + jsonpCallbackFunction: 'cbName', + }, // 透传 `axios` 需要配置的参数。例如需要传递超时时间时可添加: axiosOptions: { timeout: 10 * 1000 }, @@ -154,5 +158,12 @@ export default { /** @type { import('../../src/').ReqType } */ reqType: ('axios'), }, + /** + * jsonp-options + */ + { + name: 'jsonpOptions', + path: 'jsonp-options', + }, ], } diff --git a/examples/apis-web/index.d.ts b/examples/apis-web/index.d.ts index 52f0a09..0bf97be 100644 --- a/examples/apis-web/index.d.ts +++ b/examples/apis-web/index.d.ts @@ -21,6 +21,7 @@ export const fakeGetApi: { 'afterData': ReqFnWithAnyParams 'mockFnData': ReqFnWithAnyParams 'noAfterData': ReqFnWithAnyParams + 'jsonpOptions': ReqFnWithAnyParams 'beforeFnCookie': ReqFnWithAnyParams 'mockObjectData': ReqFnWithAnyParams 'empty-array-params': ReqFnWithAnyParams diff --git a/package.json b/package.json index 910b85d..782f791 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tua-api", - "version": "1.4.3", + "version": "1.4.4", "description": "🏗 A common tool helps converting configs to api functions", "main": "dist/TuaApi.cjs.js", "module": "dist/TuaApi.esm.js", @@ -36,8 +36,7 @@ }, "lint-staged": { "{src,test}/**/*.js": [ - "eslint --fix", - "git add" + "eslint --fix" ] }, "eslintIgnore": [ @@ -46,47 +45,47 @@ "package.json" ], "dependencies": { - "axios": "^0.19.0", + "axios": "^0.19.2", "fetch-jsonp": "^1.1.3", "koa-compose": "^4.1.0" }, "devDependencies": { - "@babel/core": "^7.6.4", - "@babel/plugin-external-helpers": "^7.2.0", - "@babel/plugin-proposal-decorators": "^7.6.0", - "@babel/plugin-proposal-object-rest-spread": "^7.6.2", - "@babel/preset-env": "^7.6.3", - "@commitlint/cli": "^8.2.0", - "@commitlint/config-conventional": "^8.2.0", - "@types/jest": "^24.0.18", - "all-contributors-cli": "^6.9.1", + "@babel/core": "^7.8.4", + "@babel/plugin-external-helpers": "^7.8.3", + "@babel/plugin-proposal-decorators": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.8.3", + "@babel/preset-env": "^7.8.4", + "@commitlint/cli": "^8.3.5", + "@commitlint/config-conventional": "^8.3.4", + "@types/jest": "^25.1.2", + "all-contributors-cli": "^6.13.0", "axios-mock-adapter": "^1.17.0", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "^10.0.3", - "babel-jest": "^24.9.0", - "codecov": "^3.6.1", - "cross-env": "^6.0.3", - "eslint": "^6.5.1", + "babel-jest": "^25.1.0", + "codecov": "^3.6.5", + "cross-env": "^7.0.0", + "eslint": "^6.8.0", "eslint-config-standard": "^14.1.0", - "eslint-plugin-import": "^2.18.2", - "eslint-plugin-node": "^10.0.0", + "eslint-plugin-import": "^2.20.1", + "eslint-plugin-node": "^11.0.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.1", - "gh-pages": "^2.1.1", - "husky": "^3.0.8", - "jest": "^24.9.0", - "lint-staged": "^9.4.2", - "rimraf": "^3.0.0", - "rollup": "^1.23.1", + "gh-pages": "^2.2.0", + "husky": "^4.2.3", + "jest": "^25.1.0", + "lint-staged": "^10.0.7", + "rimraf": "^3.0.2", + "rollup": "^1.31.1", "rollup-plugin-babel": "^4.3.3", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-eslint": "^7.0.0", "rollup-plugin-json": "^4.0.0", "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-replace": "^2.2.0", - "rollup-plugin-uglify": "^6.0.3", - "typescript": "^3.6.4", - "vuepress": "^1.1.0" + "rollup-plugin-uglify": "^6.0.4", + "typescript": "^3.7.5", + "vuepress": "^1.3.0" }, "repository": { "type": "git", diff --git a/src/exportUtils.js b/src/exportUtils.js index 1e53d06..3fccab9 100644 --- a/src/exportUtils.js +++ b/src/exportUtils.js @@ -29,7 +29,7 @@ const getSyncFnMapByApis = pipe( map(values), flatten, map(val => ({ [val.key]: val })), - mergeAll + mergeAll, ) /** @@ -53,7 +53,7 @@ const getPreFetchFnKeysBySyncFnMap = (syncFnMap) => pipe( return Object.keys(params).every(isParamNotRequired) }), - map(key => ({ key })) + map(key => ({ key })), )(syncFnMap) export { diff --git a/src/index.js b/src/index.js index df666c3..f40e772 100644 --- a/src/index.js +++ b/src/index.js @@ -61,7 +61,7 @@ class TuaApi { if (host) { logger.warn( '[host] will be deprecated, please use [baseUrl] instead!\n' + - '[host] 属性将被废弃, 请用 [baseUrl] 替代!' + '[host] 属性将被废弃, 请用 [baseUrl] 替代!', ) } @@ -109,6 +109,7 @@ class TuaApi { * @param {string} options.reqType 使用什么工具发(axios/jsonp/wx) * @param {object} options.reqParams 请求参数 * @param {object} options.header 请求的 header + * @param {string} options.callback 使用 jsonp 时标识回调函数的名称 * @param {string} options.callbackName 使用 jsonp 时的回调函数名 * @param {object} options.axiosOptions 透传 axios 配置参数 * @param {object} options.jsonpOptions 透传 fetch-jsonp 配置参数 @@ -122,7 +123,8 @@ class TuaApi { fullUrl, reqType, reqParams: data, - callbackName: jsonpCallbackFunction, + callback, + callbackName, axiosOptions, jsonpOptions, ...rest @@ -157,10 +159,13 @@ class TuaApi { return getAxiosPromise(params) } - return getFetchJsonpPromise({ - url: fullUrl, - jsonpOptions: { ...jsonpOptions, jsonpCallbackFunction }, - }) + // 防止接口返回非英文时报错 + jsonpOptions.charset = jsonpOptions.charset || 'UTF-8' + + jsonpOptions.jsonpCallback = callback || jsonpOptions.jsonpCallback + jsonpOptions.jsonpCallbackFunction = callbackName || jsonpOptions.jsonpCallbackFunction + + return getFetchJsonpPromise({ url: fullUrl, jsonpOptions }) } /** @@ -245,7 +250,7 @@ class TuaApi { if (type) { logger.warn( '[type] will be deprecated, please use [method] instead!\n' + - '[type] 属性将被废弃, 请用 [method] 替代!' + '[type] 属性将被废弃, 请用 [method] 替代!', ) } @@ -293,9 +298,6 @@ class TuaApi { runtimeParams.method = runtimeParams.method || runtimeParams.type - // 自定义回调函数名称(用于 jsonp) - runtimeParams.callbackName = runtimeParams.callbackName || `${runtimeParams.path}Callback` - // 请求的上下文信息 const ctx = { req: { args, mock: apiFn.mock, reqFnParams: {}, ...runtimeParams }, @@ -326,7 +328,7 @@ class TuaApi { .then(() => afterFn([ctx.res.data, ctx])) .then((data) => ctx.res.error ? Promise.reject(ctx.res.error) - : data || ctx.res.data + : data || ctx.res.data, ) } diff --git a/src/utils/fp.js b/src/utils/fp.js index 4ad0bd8..ab15dc0 100644 --- a/src/utils/fp.js +++ b/src/utils/fp.js @@ -3,7 +3,7 @@ const map = (fn) => (arr) => Array.isArray(arr) : pipe( Object.keys, map(key => ({ [key]: fn(arr[key]) })), - mergeAll + mergeAll, )(arr) const join = str => arr => arr.join(str) @@ -20,7 +20,7 @@ const flatten = reduce( (acc, cur) => Array.isArray(cur) ? compose(concat, flatten)(cur)(acc) : concat(cur)(acc), - [] + [], ) const merge = (acc, cur) => ({ ...acc, ...cur }) diff --git a/src/utils/params.js b/src/utils/params.js index 0edb4d0..c2506a4 100644 --- a/src/utils/params.js +++ b/src/utils/params.js @@ -16,7 +16,7 @@ import { ERROR_STRINGS } from '../constants' const getParamStrFromObj = (data = {}) => pipe( Object.keys, map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`), - join('&') + join('&'), )(data) /** @@ -74,7 +74,7 @@ const getDefaultParamObj = ({ return { [key]: returnVal } }), - reduce(merge, commonParams) + reduce(merge, commonParams), )(params) /** diff --git a/test/__tests__/jsonp.test.js b/test/__tests__/jsonp.test.js index 1092abd..d708c1a 100644 --- a/test/__tests__/jsonp.test.js +++ b/test/__tests__/jsonp.test.js @@ -1,4 +1,5 @@ import { fakeGetApi } from '@examples/apis-web/' +import fakeGetConfig from '@examples/apis-web/fake-get' import { ERROR_STRINGS } from '@/constants' jest.mock('fetch-jsonp') @@ -24,6 +25,26 @@ describe('mock data', () => { }) describe('fake jsonp requests', () => { + test('jsonp options', async () => { + const url = 'http://example-base.com/fake-get/jsonp-options' + const jsonpOptions = { + ...fakeGetConfig.jsonpOptions, + charset: 'UTF-8', + } + + await fakeGetApi.jsonpOptions() + expect(fetchJsonp).toBeCalledWith(url, jsonpOptions) + + const callback = 'test_cb' + const callbackName = 'test_cbName' + await fakeGetApi.jsonpOptions(null, { callback, callbackName }) + expect(fetchJsonp).toBeCalledWith(url, { + ...jsonpOptions, + jsonpCallback: callback, + jsonpCallbackFunction: callbackName, + }) + }) + test('async-common-params', async () => { fetchJsonp.mockResolvedValue({ json: () => data }) const resData = await fakeGetApi.acp() diff --git a/test/__tests__/wx.test.js b/test/__tests__/wx.test.js index 2bac86c..7cdc944 100644 --- a/test/__tests__/wx.test.js +++ b/test/__tests__/wx.test.js @@ -63,11 +63,12 @@ describe('middleware', () => { expect(ctx.req.prefix).toBeDefined() expect(ctx.req.reqType).toBeDefined() expect(ctx.req.reqParams).toBeDefined() - expect(ctx.req.callbackName).toBeDefined() expect(ctx.req.axiosOptions).toBeDefined() expect(ctx.req.jsonpOptions).toBeDefined() expect(ctx.req.reqFnParams).toBeDefined() + expect(ctx.req.callbackName).toBeUndefined() + await next() expect(ctx.reqTime).toBeDefined()