├── src
└── lib
│ ├── luch-request.js
│ ├── core
│ ├── dispatchRequest.js
│ ├── settle.js
│ ├── buildFullPath.js
│ ├── defaults.js
│ ├── InterceptorManager.js
│ ├── mergeConfig.js
│ └── Request.js
│ ├── helpers
│ ├── combineURLs.js
│ ├── isAbsoluteURL.js
│ └── buildURL.js
│ ├── utils.js
│ ├── adapters
│ └── index.js
│ ├── luch-request.d.ts
│ └── utils
│ └── clone.js
├── DCloud
└── luch-request
│ ├── index.js
│ ├── core
│ ├── dispatchRequest.js
│ ├── settle.js
│ ├── buildFullPath.js
│ ├── defaults.js
│ ├── InterceptorManager.js
│ ├── mergeConfig.js
│ └── Request.js
│ ├── helpers
│ ├── combineURLs.js
│ ├── isAbsoluteURL.js
│ └── buildURL.js
│ ├── utils.js
│ ├── adapters
│ └── index.js
│ ├── index.d.ts
│ └── utils
│ └── clone.js
├── test
├── dev-test
│ ├── static
│ │ └── logo.jpg
│ ├── utils
│ │ └── luch-request
│ │ │ ├── index.js
│ │ │ ├── core
│ │ │ ├── dispatchRequest.js
│ │ │ ├── settle.js
│ │ │ ├── buildFullPath.js
│ │ │ ├── defaults.js
│ │ │ ├── InterceptorManager.js
│ │ │ ├── mergeConfig.js
│ │ │ └── Request.js
│ │ │ ├── helpers
│ │ │ ├── combineURLs.js
│ │ │ ├── isAbsoluteURL.js
│ │ │ └── buildURL.js
│ │ │ ├── utils.js
│ │ │ ├── adapters
│ │ │ └── index.js
│ │ │ └── index.d.ts
│ ├── main.js
│ ├── App.vue
│ ├── pages.json
│ ├── uni.scss
│ ├── api
│ │ └── service.js
│ ├── manifest.json
│ └── pages
│ │ └── index
│ │ └── index.vue
└── types-test.ts
├── example
└── request-demo
│ ├── utils
│ └── luch-request
│ │ ├── index.js
│ │ ├── core
│ │ ├── dispatchRequest.js
│ │ ├── settle.js
│ │ ├── buildFullPath.js
│ │ ├── defaults.js
│ │ ├── InterceptorManager.js
│ │ ├── mergeConfig.js
│ │ └── Request.js
│ │ ├── helpers
│ │ ├── combineURLs.js
│ │ ├── isAbsoluteURL.js
│ │ └── buildURL.js
│ │ ├── utils.js
│ │ ├── adapters
│ │ └── index.js
│ │ └── index.d.ts
│ ├── static
│ └── logo.jpg
│ ├── main.js
│ ├── App.vue
│ ├── pages.json
│ ├── api
│ ├── goods.js
│ └── service.js
│ ├── uni.scss
│ ├── pages
│ ├── goods-list
│ │ └── goods-list.vue
│ └── index
│ │ └── index.vue
│ └── manifest.json
├── docs
├── .vuepress
│ ├── public
│ │ └── assets
│ │ │ └── img
│ │ │ └── logo.jpg
│ ├── components
│ │ └── cm-notice.vue
│ └── config.js
├── resources
│ └── article.md
├── acknowledgement
│ └── README.md
├── README.md
├── issue
│ └── README.md
└── handbook
│ └── README.md
├── babel.config.js
├── .npmignore
├── .gitignore
├── node
├── zipDCloudDemo.js
└── zipDCloudPlugin.js
├── gruntfile.js
├── .eslintrc.js
├── .github
└── .workflow
│ └── doc_pub.yml
├── LICENSE.txt
├── rollup.config.js
├── history.md
├── package.json
└── tsconfig.json
/src/lib/luch-request.js:
--------------------------------------------------------------------------------
1 | import Request from './core/Request'
2 | export default Request
3 |
--------------------------------------------------------------------------------
/DCloud/luch-request/index.js:
--------------------------------------------------------------------------------
1 | import Request from './core/Request'
2 | export default Request
3 |
--------------------------------------------------------------------------------
/test/dev-test/static/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lei-mu/luch-request/HEAD/test/dev-test/static/logo.jpg
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/index.js:
--------------------------------------------------------------------------------
1 | import Request from './core/Request'
2 | export default Request
3 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/index.js:
--------------------------------------------------------------------------------
1 | import Request from './core/Request'
2 | export default Request
3 |
--------------------------------------------------------------------------------
/example/request-demo/static/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lei-mu/luch-request/HEAD/example/request-demo/static/logo.jpg
--------------------------------------------------------------------------------
/docs/.vuepress/public/assets/img/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lei-mu/luch-request/HEAD/docs/.vuepress/public/assets/img/logo.jpg
--------------------------------------------------------------------------------
/src/lib/core/dispatchRequest.js:
--------------------------------------------------------------------------------
1 | import adapter from '../adapters/index'
2 |
3 |
4 | export default (config) => {
5 | return adapter(config)
6 | }
7 |
--------------------------------------------------------------------------------
/DCloud/luch-request/core/dispatchRequest.js:
--------------------------------------------------------------------------------
1 | import adapter from '../adapters/index'
2 |
3 |
4 | export default (config) => {
5 | return adapter(config)
6 | }
7 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/core/dispatchRequest.js:
--------------------------------------------------------------------------------
1 | import adapter from '../adapters/index'
2 |
3 |
4 | export default (config) => {
5 | return adapter(config)
6 | }
7 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@babel/preset-env'],
3 | plugins: [ "@babel/plugin-transform-arrow-functions", "@babel/plugin-proposal-class-properties" ]
4 | };
5 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/core/dispatchRequest.js:
--------------------------------------------------------------------------------
1 | import adapter from '../adapters/index'
2 |
3 |
4 | export default (config) => {
5 | return adapter(config)
6 | }
7 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | **/.*
2 | *.iml
3 | example/
4 | node_modules/
5 | dist/
6 | docs/
7 | DCloud/
8 | test/
9 | node/
10 | zipDist/
11 | babel.config.js
12 | gruntfile.js
13 | rollup.config.js
14 | tsconfig.json
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .idea
3 | .tscache
4 | .DS_Store
5 | .hbuilderx
6 | yarn-error.log
7 | node_modules/
8 | dist
9 | DCloud/*
10 | !DCloud/luch-request/
11 |
12 |
13 | zipDist/
14 |
15 | example/*
16 | !/example/request-demo
17 |
--------------------------------------------------------------------------------
/test/dev-test/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App'
3 | import { http } from '@/api/service.js' // 全局挂载引入,配置相关在该index.js文件里修改
4 |
5 | Vue.prototype.$http = http
6 | Vue.config.productionTip = false
7 |
8 | App.mpType = 'app'
9 |
10 | const app = new Vue({
11 | ...App
12 | })
13 | app.$mount()
14 |
--------------------------------------------------------------------------------
/example/request-demo/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App'
3 | import { http } from '@/api/service.js' // 全局挂载引入,配置相关在该index.js文件里修改
4 |
5 | Vue.prototype.$http = http
6 | Vue.config.productionTip = false
7 |
8 | App.mpType = 'app'
9 |
10 | const app = new Vue({
11 | ...App
12 | })
13 | app.$mount()
14 |
--------------------------------------------------------------------------------
/test/dev-test/App.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
18 |
--------------------------------------------------------------------------------
/example/request-demo/App.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
18 |
--------------------------------------------------------------------------------
/test/dev-test/pages.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
3 | {
4 | "path": "pages/index/index",
5 | "style": {
6 | }
7 | }
8 | ],
9 | "globalStyle": {
10 | "navigationBarTextStyle": "black",
11 | "navigationBarTitleText": "luch-request dev-test",
12 | "navigationBarBackgroundColor": "#F8F8F8",
13 | "backgroundColor": "#F8F8F8"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/node/zipDCloudDemo.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var archiver = require('archiver')
3 |
4 | var output = fs.createWriteStream('zipDist/request-demo.zip')
5 |
6 | var archive = archiver('zip')
7 |
8 | archive.on('error', function(err){
9 | throw err
10 | })
11 | const buildDemo = () => {
12 | archive.pipe(output)
13 | archive.directory('DCloud/request-demo', 'request-demo')
14 | archive.finalize()
15 | }
16 |
17 | buildDemo()
18 |
--------------------------------------------------------------------------------
/node/zipDCloudPlugin.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var archiver = require('archiver')
3 |
4 | var output = fs.createWriteStream('zipDist/luch-request.zip')
5 |
6 | var archive = archiver('zip')
7 |
8 | archive.on('error', function(err){
9 | throw err
10 | })
11 | const buildRequest = () => {
12 | archive.pipe(output)
13 | archive.directory('DCloud/luch-request', 'luch-request')
14 | archive.finalize()
15 | }
16 | buildRequest()
17 |
--------------------------------------------------------------------------------
/src/lib/helpers/combineURLs.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * Creates a new URL by combining the specified URLs
5 | *
6 | * @param {string} baseURL The base URL
7 | * @param {string} relativeURL The relative URL
8 | * @returns {string} The combined URL
9 | */
10 | export default function combineURLs(baseURL, relativeURL) {
11 | return relativeURL
12 | ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
13 | : baseURL
14 | }
15 |
--------------------------------------------------------------------------------
/DCloud/luch-request/helpers/combineURLs.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * Creates a new URL by combining the specified URLs
5 | *
6 | * @param {string} baseURL The base URL
7 | * @param {string} relativeURL The relative URL
8 | * @returns {string} The combined URL
9 | */
10 | export default function combineURLs(baseURL, relativeURL) {
11 | return relativeURL
12 | ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
13 | : baseURL
14 | }
15 |
--------------------------------------------------------------------------------
/gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | require('load-grunt-tasks')(grunt) // npm install --save-dev load-grunt-tasks
3 |
4 | grunt.initConfig({
5 | babel: {
6 | options: {
7 | sourceMap: true,
8 | presets: ['@babel/preset-env']
9 | },
10 | dist: {
11 | files: {
12 | 'dist/app.js': 'src/index.js'
13 | }
14 | }
15 | }
16 | })
17 |
18 | grunt.registerTask('default', ['babel'])
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/helpers/combineURLs.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * Creates a new URL by combining the specified URLs
5 | *
6 | * @param {string} baseURL The base URL
7 | * @param {string} relativeURL The relative URL
8 | * @returns {string} The combined URL
9 | */
10 | export default function combineURLs(baseURL, relativeURL) {
11 | return relativeURL
12 | ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
13 | : baseURL
14 | }
15 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/helpers/combineURLs.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * Creates a new URL by combining the specified URLs
5 | *
6 | * @param {string} baseURL The base URL
7 | * @param {string} relativeURL The relative URL
8 | * @returns {string} The combined URL
9 | */
10 | export default function combineURLs(baseURL, relativeURL) {
11 | return relativeURL
12 | ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
13 | : baseURL
14 | }
15 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "env": {
3 | "browser": true,
4 | "commonjs": true,
5 | "es6": true
6 | },
7 | "extends": "eslint:recommended",
8 | "globals": {
9 | "Atomics": "readonly",
10 | "SharedArrayBuffer": "readonly",
11 | "uni": true
12 | },
13 | parser: "babel-eslint",
14 | "parserOptions": {
15 | "ecmaVersion": 2018,
16 | },
17 | "rules": {
18 | semi: ['error', 'never'], // 结尾不用写分号
19 | "indent": ["error", 2]
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/example/request-demo/pages.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | {
4 | "path": "pages/index/index",
5 | "style": {
6 | }
7 | }
8 | ,{
9 | "path" : "pages/goods-list/goods-list",
10 | "style" : {}
11 | }
12 | ],
13 | "globalStyle": {
14 | "navigationBarTextStyle": "black",
15 | "navigationBarTitleText": "luch-request demo",
16 | "navigationBarBackgroundColor": "#F8F8F8",
17 | "backgroundColor": "#F8F8F8"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/docs/.vuepress/components/cm-notice.vue:
--------------------------------------------------------------------------------
1 |
2 | {{message}}
3 |
4 |
20 |
31 |
--------------------------------------------------------------------------------
/src/lib/core/settle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Resolve or reject a Promise based on response status.
3 | *
4 | * @param {Function} resolve A function that resolves the promise.
5 | * @param {Function} reject A function that rejects the promise.
6 | * @param {object} response The response.
7 | */
8 | export default function settle(resolve, reject, response) {
9 | const validateStatus = response.config.validateStatus
10 | const status = response.statusCode
11 | if (status && (!validateStatus || validateStatus(status))) {
12 | resolve(response)
13 | } else {
14 | reject(response)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/DCloud/luch-request/core/settle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Resolve or reject a Promise based on response status.
3 | *
4 | * @param {Function} resolve A function that resolves the promise.
5 | * @param {Function} reject A function that rejects the promise.
6 | * @param {object} response The response.
7 | */
8 | export default function settle(resolve, reject, response) {
9 | const validateStatus = response.config.validateStatus
10 | const status = response.statusCode
11 | if (status && (!validateStatus || validateStatus(status))) {
12 | resolve(response)
13 | } else {
14 | reject(response)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/core/settle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Resolve or reject a Promise based on response status.
3 | *
4 | * @param {Function} resolve A function that resolves the promise.
5 | * @param {Function} reject A function that rejects the promise.
6 | * @param {object} response The response.
7 | */
8 | export default function settle(resolve, reject, response) {
9 | const validateStatus = response.config.validateStatus
10 | const status = response.statusCode
11 | if (status && (!validateStatus || validateStatus(status))) {
12 | resolve(response)
13 | } else {
14 | reject(response)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/core/settle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Resolve or reject a Promise based on response status.
3 | *
4 | * @param {Function} resolve A function that resolves the promise.
5 | * @param {Function} reject A function that rejects the promise.
6 | * @param {object} response The response.
7 | */
8 | export default function settle(resolve, reject, response) {
9 | const validateStatus = response.config.validateStatus
10 | const status = response.statusCode
11 | if (status && (!validateStatus || validateStatus(status))) {
12 | resolve(response)
13 | } else {
14 | reject(response)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/lib/helpers/isAbsoluteURL.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * Determines whether the specified URL is absolute
5 | *
6 | * @param {string} url The URL to test
7 | * @returns {boolean} True if the specified URL is absolute, otherwise false
8 | */
9 | export default function isAbsoluteURL(url) {
10 | // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL).
11 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
12 | // by any combination of letters, digits, plus, period, or hyphen.
13 | return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
14 | }
15 |
--------------------------------------------------------------------------------
/DCloud/luch-request/helpers/isAbsoluteURL.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * Determines whether the specified URL is absolute
5 | *
6 | * @param {string} url The URL to test
7 | * @returns {boolean} True if the specified URL is absolute, otherwise false
8 | */
9 | export default function isAbsoluteURL(url) {
10 | // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL).
11 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
12 | // by any combination of letters, digits, plus, period, or hyphen.
13 | return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
14 | }
15 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/helpers/isAbsoluteURL.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * Determines whether the specified URL is absolute
5 | *
6 | * @param {string} url The URL to test
7 | * @returns {boolean} True if the specified URL is absolute, otherwise false
8 | */
9 | export default function isAbsoluteURL(url) {
10 | // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL).
11 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
12 | // by any combination of letters, digits, plus, period, or hyphen.
13 | return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
14 | }
15 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/helpers/isAbsoluteURL.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | /**
4 | * Determines whether the specified URL is absolute
5 | *
6 | * @param {string} url The URL to test
7 | * @returns {boolean} True if the specified URL is absolute, otherwise false
8 | */
9 | export default function isAbsoluteURL(url) {
10 | // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL).
11 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
12 | // by any combination of letters, digits, plus, period, or hyphen.
13 | return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
14 | }
15 |
--------------------------------------------------------------------------------
/example/request-demo/api/goods.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 商品相关api
3 | */
4 | import {
5 | http
6 | } from '@/api/service.js'
7 |
8 | /**
9 | * 查询商品列表
10 | * @param {Object} params - 查询参数
11 | */
12 | export const getGoodsList = (params) => {
13 | return http.get('/api/user/list', {
14 | params
15 | })
16 | }
17 |
18 | // 通用请求方法middleware 演示。文档:https://www.quanzhan.co/luch-request/guide/3.x/#middleware
19 | /**
20 | * 查询商品信息
21 | * @param {Object} data - 查询数据
22 | * @param {Object} params - 查询params参数
23 | */
24 | export const getGoodsInfo = (data, params) => {
25 | return http.middleware({
26 | method: 'POST', // 必须大写
27 | url: '/api/user/update',
28 | data: data,
29 | params: params,
30 | custom: {
31 | auth: true
32 | }
33 | })
34 | }
35 |
--------------------------------------------------------------------------------
/src/lib/core/buildFullPath.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import isAbsoluteURL from '../helpers/isAbsoluteURL'
4 | import combineURLs from '../helpers/combineURLs'
5 |
6 | /**
7 | * Creates a new URL by combining the baseURL with the requestedURL,
8 | * only when the requestedURL is not already an absolute URL.
9 | * If the requestURL is absolute, this function returns the requestedURL untouched.
10 | *
11 | * @param {string} baseURL The base URL
12 | * @param {string} requestedURL Absolute or relative URL to combine
13 | * @returns {string} The combined full path
14 | */
15 | export default function buildFullPath(baseURL, requestedURL) {
16 | if (baseURL && !isAbsoluteURL(requestedURL)) {
17 | return combineURLs(baseURL, requestedURL)
18 | }
19 | return requestedURL
20 | }
21 |
--------------------------------------------------------------------------------
/src/lib/core/defaults.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 默认的全局配置
3 | */
4 |
5 |
6 | export default {
7 | baseURL: '',
8 | header: {},
9 | method: 'GET',
10 | dataType: 'json',
11 | paramsSerializer: null,
12 | // #ifndef MP-ALIPAY
13 | responseType: 'text',
14 | // #endif
15 | custom: {},
16 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
17 | timeout: 60000,
18 | // #endif
19 | // #ifdef APP-PLUS
20 | sslVerify: true,
21 | // #endif
22 | // #ifdef H5
23 | withCredentials: false,
24 | // #endif
25 | // #ifdef APP-PLUS
26 | firstIpv4: false,
27 | // #endif
28 | validateStatus: function validateStatus(status) {
29 | return status >= 200 && status < 300
30 | },
31 | // 是否尝试将响应数据json化
32 | forcedJSONParsing: true
33 | }
34 |
--------------------------------------------------------------------------------
/.github/.workflow/doc_pub.yml:
--------------------------------------------------------------------------------
1 | # action 的名称
2 | name: doc_pub
3 |
4 | # 触发条件:在 push 到 docs 分支后
5 | on:
6 | push:
7 | branches:
8 | - docs
9 |
10 | # 任务
11 | jobs:
12 | build-and-deploy:
13 | # 服务器环境:最新版 Ubuntu
14 | runs-on: ubuntu-latest
15 | steps:
16 | # 拉取代码
17 | - name: Checkout
18 | uses: actions/checkout@docs
19 | with:
20 | persist-credentials: false
21 |
22 | - name: vuepress-deploy
23 | uses: jenkey2011/vuepress-deploy@master
24 | env:
25 | ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
26 | TARGET_REPO: lei-mu/luch-request
27 | TARGET_BRANCH: gh_pages
28 | BUILD_SCRIPT: npm && npm run docs:build
29 | BUILD_DIR: docs/.vuepress/dist/
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/DCloud/luch-request/core/buildFullPath.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import isAbsoluteURL from '../helpers/isAbsoluteURL'
4 | import combineURLs from '../helpers/combineURLs'
5 |
6 | /**
7 | * Creates a new URL by combining the baseURL with the requestedURL,
8 | * only when the requestedURL is not already an absolute URL.
9 | * If the requestURL is absolute, this function returns the requestedURL untouched.
10 | *
11 | * @param {string} baseURL The base URL
12 | * @param {string} requestedURL Absolute or relative URL to combine
13 | * @returns {string} The combined full path
14 | */
15 | export default function buildFullPath(baseURL, requestedURL) {
16 | if (baseURL && !isAbsoluteURL(requestedURL)) {
17 | return combineURLs(baseURL, requestedURL)
18 | }
19 | return requestedURL
20 | }
21 |
--------------------------------------------------------------------------------
/DCloud/luch-request/core/defaults.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 默认的全局配置
3 | */
4 |
5 |
6 | export default {
7 | baseURL: '',
8 | header: {},
9 | method: 'GET',
10 | dataType: 'json',
11 | paramsSerializer: null,
12 | // #ifndef MP-ALIPAY
13 | responseType: 'text',
14 | // #endif
15 | custom: {},
16 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
17 | timeout: 60000,
18 | // #endif
19 | // #ifdef APP-PLUS
20 | sslVerify: true,
21 | // #endif
22 | // #ifdef H5
23 | withCredentials: false,
24 | // #endif
25 | // #ifdef APP-PLUS
26 | firstIpv4: false,
27 | // #endif
28 | validateStatus: function validateStatus(status) {
29 | return status >= 200 && status < 300
30 | },
31 | // 是否尝试将响应数据json化
32 | forcedJSONParsing: true
33 | }
34 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/core/buildFullPath.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import isAbsoluteURL from '../helpers/isAbsoluteURL'
4 | import combineURLs from '../helpers/combineURLs'
5 |
6 | /**
7 | * Creates a new URL by combining the baseURL with the requestedURL,
8 | * only when the requestedURL is not already an absolute URL.
9 | * If the requestURL is absolute, this function returns the requestedURL untouched.
10 | *
11 | * @param {string} baseURL The base URL
12 | * @param {string} requestedURL Absolute or relative URL to combine
13 | * @returns {string} The combined full path
14 | */
15 | export default function buildFullPath(baseURL, requestedURL) {
16 | if (baseURL && !isAbsoluteURL(requestedURL)) {
17 | return combineURLs(baseURL, requestedURL)
18 | }
19 | return requestedURL
20 | }
21 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/core/defaults.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 默认的全局配置
3 | */
4 |
5 |
6 | export default {
7 | baseURL: '',
8 | header: {},
9 | method: 'GET',
10 | dataType: 'json',
11 | paramsSerializer: null,
12 | // #ifndef MP-ALIPAY
13 | responseType: 'text',
14 | // #endif
15 | custom: {},
16 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
17 | timeout: 60000,
18 | // #endif
19 | // #ifdef APP-PLUS
20 | sslVerify: true,
21 | // #endif
22 | // #ifdef H5
23 | withCredentials: false,
24 | // #endif
25 | // #ifdef APP-PLUS
26 | firstIpv4: false,
27 | // #endif
28 | validateStatus: function validateStatus(status) {
29 | return status >= 200 && status < 300
30 | },
31 | // 是否尝试将响应数据json化
32 | forcedJSONParsing: true
33 | }
34 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/core/buildFullPath.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import isAbsoluteURL from '../helpers/isAbsoluteURL'
4 | import combineURLs from '../helpers/combineURLs'
5 |
6 | /**
7 | * Creates a new URL by combining the baseURL with the requestedURL,
8 | * only when the requestedURL is not already an absolute URL.
9 | * If the requestURL is absolute, this function returns the requestedURL untouched.
10 | *
11 | * @param {string} baseURL The base URL
12 | * @param {string} requestedURL Absolute or relative URL to combine
13 | * @returns {string} The combined full path
14 | */
15 | export default function buildFullPath(baseURL, requestedURL) {
16 | if (baseURL && !isAbsoluteURL(requestedURL)) {
17 | return combineURLs(baseURL, requestedURL)
18 | }
19 | return requestedURL
20 | }
21 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/core/defaults.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 默认的全局配置
3 | */
4 |
5 |
6 | export default {
7 | baseURL: '',
8 | header: {},
9 | method: 'GET',
10 | dataType: 'json',
11 | paramsSerializer: null,
12 | // #ifndef MP-ALIPAY
13 | responseType: 'text',
14 | // #endif
15 | custom: {},
16 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
17 | timeout: 60000,
18 | // #endif
19 | // #ifdef APP-PLUS
20 | sslVerify: true,
21 | // #endif
22 | // #ifdef H5
23 | withCredentials: false,
24 | // #endif
25 | // #ifdef APP-PLUS
26 | firstIpv4: false,
27 | // #endif
28 | validateStatus: function validateStatus(status) {
29 | return status >= 200 && status < 300
30 | },
31 | // 是否尝试将响应数据json化
32 | forcedJSONParsing: true
33 | }
34 |
--------------------------------------------------------------------------------
/docs/resources/article.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar: auto
3 | title: 相关文章
4 | ---
5 |
6 | 前言
7 | ------------
8 |
9 | 以下为本人遇到的和luch-request有关的文章,除了本人的文章,其他的本人不保证可行性。
10 | 如果你也有luch-request 相关的文章想放到这里,可以给我发邮件或者点击下方的`帮助我改善此页面`进行编辑
11 | 如果你不想自己的文章/名字显示到这里,也可以发邮件联系或者qq
12 | 侵权删
13 |
14 | jwt 无痛刷新
15 | ------------
16 |
17 | #### luch[官方]
18 | [luch-request jwt 无痛刷新最佳实践[推荐]](https://quanzhan.co/archives/51)
19 |
20 |
21 | #### learnku php_yt
22 | uniapp 小程序 Laravel+jwt 权限认证完整系列
23 |
24 | #### dcloud kysin
25 | axios如何利用promise无痛刷新token
26 |
27 | axios如何利用promise无痛刷新token二
28 |
29 | axios+async/await无痛刷新token
30 |
31 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) [2022] [luch]
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/test/types-test.ts:
--------------------------------------------------------------------------------
1 | import LuchRequest from "../src/lib/luch-request"
2 | const luchRequest = new LuchRequest();
3 |
4 | luchRequest.setConfig(config => {
5 | return config
6 | })
7 | luchRequest.post("url", { 123: 60 }, {
8 | baseURL: "/api"
9 | }).then(response=>{
10 | response.config
11 | })
12 | // LuchRequestAbstract
13 | luchRequest
14 |
15 | // LuchRequestConfig
16 | luchRequest.config
17 |
18 | const data = new FormData()
19 | // LuchRequestAbstract.interceptors
20 | luchRequest.interceptors.request.use(config => {
21 | return config
22 | }, (config) => {
23 | return Promise.reject(config)
24 | })
25 | luchRequest.interceptors.response.use(
26 | response => {
27 | return response.data
28 | },
29 | (response) => {
30 | return Promise.reject(response)
31 | }
32 | )
33 |
34 | // mock request login
35 | interface UserInfo {
36 | username: string;
37 | phone: string | number;
38 | }
39 | export const reqLogin = () => {
40 | return luchRequest.get("/api/login")
41 | }
42 | // mock get userInfo
43 | ; (async () => {
44 | const result = await reqLogin()
45 | // interface UserInfo
46 | result.data
47 | })
48 |
49 | // mock request download
50 | const url = "xxx/xxx/xxx/xxx"
51 | ; (async () => {
52 | const result = await luchRequest.download(url)
53 | result.tempFilePath
54 | })
--------------------------------------------------------------------------------
/docs/acknowledgement/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar: auto
3 | title: 鸣谢
4 | ---
5 |
6 | 前言
7 | ------------
8 | 感谢每一位贡献者
9 | 对插件**做出贡献**或对此插件进行**打赏**,本人将在此处列出,以表示感谢
10 | 贡献者可以提出一个名称、一个网址显示在此处。
11 | 如果你不想自己的名字显示在这里,可以发邮件或者qq向我说明情况
12 | 侵权删!
13 |
14 | 土豪赞赏
15 | ------------
16 |
17 |
18 |
19 |
20 |
21 | 赞助名单
22 | ------------
23 | - `lishuda@kxtsoft.com`
24 | - qq:`78****245`
25 | - `346****37@qq.com`
26 | - 名字找不到了 0.0
27 | - 记得
28 | - ...
29 |
30 | 插件贡献
31 | ------------
32 | - 高卓彦 提出`3.0.0`版本存在所有请求都为GET请求bug,已在3.0.1版本修复
33 | - `353754391@qq.com` 提出多实例共用同一全局配置bug
34 | - `370681295@qq.com` - @zouyaoji 提出 ` params ` 选项参数格式化数组等存在问题。已改为axios 参数格式化方案。
35 | - `TuiMao233` - @TuiMao233 提供index.d.ts 文件支持,十分感谢。
36 | - ...
37 |
--------------------------------------------------------------------------------
/src/lib/core/InterceptorManager.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 |
4 | function InterceptorManager() {
5 | this.handlers = []
6 | }
7 |
8 | /**
9 | * Add a new interceptor to the stack
10 | *
11 | * @param {Function} fulfilled The function to handle `then` for a `Promise`
12 | * @param {Function} rejected The function to handle `reject` for a `Promise`
13 | *
14 | * @return {Number} An ID used to remove interceptor later
15 | */
16 | InterceptorManager.prototype.use = function use(fulfilled, rejected) {
17 | this.handlers.push({
18 | fulfilled: fulfilled,
19 | rejected: rejected
20 | })
21 | return this.handlers.length - 1
22 | }
23 |
24 | /**
25 | * Remove an interceptor from the stack
26 | *
27 | * @param {Number} id The ID that was returned by `use`
28 | */
29 | InterceptorManager.prototype.eject = function eject(id) {
30 | if (this.handlers[id]) {
31 | this.handlers[id] = null
32 | }
33 | }
34 |
35 | /**
36 | * Iterate over all the registered interceptors
37 | *
38 | * This method is particularly useful for skipping over any
39 | * interceptors that may have become `null` calling `eject`.
40 | *
41 | * @param {Function} fn The function to call for each interceptor
42 | */
43 | InterceptorManager.prototype.forEach = function forEach(fn) {
44 | this.handlers.forEach(h => {
45 | if (h !== null) {
46 | fn(h)
47 | }
48 | })
49 | }
50 |
51 | export default InterceptorManager
52 |
--------------------------------------------------------------------------------
/DCloud/luch-request/core/InterceptorManager.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 |
4 | function InterceptorManager() {
5 | this.handlers = []
6 | }
7 |
8 | /**
9 | * Add a new interceptor to the stack
10 | *
11 | * @param {Function} fulfilled The function to handle `then` for a `Promise`
12 | * @param {Function} rejected The function to handle `reject` for a `Promise`
13 | *
14 | * @return {Number} An ID used to remove interceptor later
15 | */
16 | InterceptorManager.prototype.use = function use(fulfilled, rejected) {
17 | this.handlers.push({
18 | fulfilled: fulfilled,
19 | rejected: rejected
20 | })
21 | return this.handlers.length - 1
22 | }
23 |
24 | /**
25 | * Remove an interceptor from the stack
26 | *
27 | * @param {Number} id The ID that was returned by `use`
28 | */
29 | InterceptorManager.prototype.eject = function eject(id) {
30 | if (this.handlers[id]) {
31 | this.handlers[id] = null
32 | }
33 | }
34 |
35 | /**
36 | * Iterate over all the registered interceptors
37 | *
38 | * This method is particularly useful for skipping over any
39 | * interceptors that may have become `null` calling `eject`.
40 | *
41 | * @param {Function} fn The function to call for each interceptor
42 | */
43 | InterceptorManager.prototype.forEach = function forEach(fn) {
44 | this.handlers.forEach(h => {
45 | if (h !== null) {
46 | fn(h)
47 | }
48 | })
49 | }
50 |
51 | export default InterceptorManager
52 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/core/InterceptorManager.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 |
4 | function InterceptorManager() {
5 | this.handlers = []
6 | }
7 |
8 | /**
9 | * Add a new interceptor to the stack
10 | *
11 | * @param {Function} fulfilled The function to handle `then` for a `Promise`
12 | * @param {Function} rejected The function to handle `reject` for a `Promise`
13 | *
14 | * @return {Number} An ID used to remove interceptor later
15 | */
16 | InterceptorManager.prototype.use = function use(fulfilled, rejected) {
17 | this.handlers.push({
18 | fulfilled: fulfilled,
19 | rejected: rejected
20 | })
21 | return this.handlers.length - 1
22 | }
23 |
24 | /**
25 | * Remove an interceptor from the stack
26 | *
27 | * @param {Number} id The ID that was returned by `use`
28 | */
29 | InterceptorManager.prototype.eject = function eject(id) {
30 | if (this.handlers[id]) {
31 | this.handlers[id] = null
32 | }
33 | }
34 |
35 | /**
36 | * Iterate over all the registered interceptors
37 | *
38 | * This method is particularly useful for skipping over any
39 | * interceptors that may have become `null` calling `eject`.
40 | *
41 | * @param {Function} fn The function to call for each interceptor
42 | */
43 | InterceptorManager.prototype.forEach = function forEach(fn) {
44 | this.handlers.forEach(h => {
45 | if (h !== null) {
46 | fn(h)
47 | }
48 | })
49 | }
50 |
51 | export default InterceptorManager
52 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/core/InterceptorManager.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 |
4 | function InterceptorManager() {
5 | this.handlers = []
6 | }
7 |
8 | /**
9 | * Add a new interceptor to the stack
10 | *
11 | * @param {Function} fulfilled The function to handle `then` for a `Promise`
12 | * @param {Function} rejected The function to handle `reject` for a `Promise`
13 | *
14 | * @return {Number} An ID used to remove interceptor later
15 | */
16 | InterceptorManager.prototype.use = function use(fulfilled, rejected) {
17 | this.handlers.push({
18 | fulfilled: fulfilled,
19 | rejected: rejected
20 | })
21 | return this.handlers.length - 1
22 | }
23 |
24 | /**
25 | * Remove an interceptor from the stack
26 | *
27 | * @param {Number} id The ID that was returned by `use`
28 | */
29 | InterceptorManager.prototype.eject = function eject(id) {
30 | if (this.handlers[id]) {
31 | this.handlers[id] = null
32 | }
33 | }
34 |
35 | /**
36 | * Iterate over all the registered interceptors
37 | *
38 | * This method is particularly useful for skipping over any
39 | * interceptors that may have become `null` calling `eject`.
40 | *
41 | * @param {Function} fn The function to call for each interceptor
42 | */
43 | InterceptorManager.prototype.forEach = function forEach(fn) {
44 | this.handlers.forEach(h => {
45 | if (h !== null) {
46 | fn(h)
47 | }
48 | })
49 | }
50 |
51 | export default InterceptorManager
52 |
--------------------------------------------------------------------------------
/src/lib/helpers/buildURL.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import * as utils from './../utils'
4 |
5 | function encode(val) {
6 | return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']')
7 | }
8 |
9 | /**
10 | * Build a URL by appending params to the end
11 | *
12 | * @param {string} url The base of the url (e.g., http://www.google.com)
13 | * @param {object} [params] The params to be appended
14 | * @returns {string} The formatted url
15 | */
16 | export default function buildURL(url, params, paramsSerializer) {
17 | /*eslint no-param-reassign:0*/
18 | if (!params) {
19 | return url
20 | }
21 |
22 | var serializedParams
23 | if (paramsSerializer) {
24 | serializedParams = paramsSerializer(params)
25 | } else if (utils.isURLSearchParams(params)) {
26 | serializedParams = params.toString()
27 | } else {
28 | var parts = []
29 |
30 | utils.forEach(params, function serialize(val, key) {
31 | if (val === null || typeof val === 'undefined') {
32 | return
33 | }
34 |
35 | if (utils.isArray(val)) {
36 | key = key + '[]'
37 | } else {
38 | val = [val]
39 | }
40 |
41 | utils.forEach(val, function parseValue(v) {
42 | if (utils.isDate(v)) {
43 | v = v.toISOString()
44 | } else if (utils.isObject(v)) {
45 | v = JSON.stringify(v)
46 | }
47 | parts.push(encode(key) + '=' + encode(v))
48 | })
49 | })
50 |
51 | serializedParams = parts.join('&')
52 | }
53 |
54 | if (serializedParams) {
55 | var hashmarkIndex = url.indexOf('#')
56 | if (hashmarkIndex !== -1) {
57 | url = url.slice(0, hashmarkIndex)
58 | }
59 |
60 | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
61 | }
62 |
63 | return url
64 | }
65 |
--------------------------------------------------------------------------------
/DCloud/luch-request/helpers/buildURL.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import * as utils from './../utils'
4 |
5 | function encode(val) {
6 | return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']')
7 | }
8 |
9 | /**
10 | * Build a URL by appending params to the end
11 | *
12 | * @param {string} url The base of the url (e.g., http://www.google.com)
13 | * @param {object} [params] The params to be appended
14 | * @returns {string} The formatted url
15 | */
16 | export default function buildURL(url, params, paramsSerializer) {
17 | /*eslint no-param-reassign:0*/
18 | if (!params) {
19 | return url
20 | }
21 |
22 | var serializedParams
23 | if (paramsSerializer) {
24 | serializedParams = paramsSerializer(params)
25 | } else if (utils.isURLSearchParams(params)) {
26 | serializedParams = params.toString()
27 | } else {
28 | var parts = []
29 |
30 | utils.forEach(params, function serialize(val, key) {
31 | if (val === null || typeof val === 'undefined') {
32 | return
33 | }
34 |
35 | if (utils.isArray(val)) {
36 | key = key + '[]'
37 | } else {
38 | val = [val]
39 | }
40 |
41 | utils.forEach(val, function parseValue(v) {
42 | if (utils.isDate(v)) {
43 | v = v.toISOString()
44 | } else if (utils.isObject(v)) {
45 | v = JSON.stringify(v)
46 | }
47 | parts.push(encode(key) + '=' + encode(v))
48 | })
49 | })
50 |
51 | serializedParams = parts.join('&')
52 | }
53 |
54 | if (serializedParams) {
55 | var hashmarkIndex = url.indexOf('#')
56 | if (hashmarkIndex !== -1) {
57 | url = url.slice(0, hashmarkIndex)
58 | }
59 |
60 | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
61 | }
62 |
63 | return url
64 | }
65 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/helpers/buildURL.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import * as utils from './../utils'
4 |
5 | function encode(val) {
6 | return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']')
7 | }
8 |
9 | /**
10 | * Build a URL by appending params to the end
11 | *
12 | * @param {string} url The base of the url (e.g., http://www.google.com)
13 | * @param {object} [params] The params to be appended
14 | * @returns {string} The formatted url
15 | */
16 | export default function buildURL(url, params, paramsSerializer) {
17 | /*eslint no-param-reassign:0*/
18 | if (!params) {
19 | return url
20 | }
21 |
22 | var serializedParams
23 | if (paramsSerializer) {
24 | serializedParams = paramsSerializer(params)
25 | } else if (utils.isURLSearchParams(params)) {
26 | serializedParams = params.toString()
27 | } else {
28 | var parts = []
29 |
30 | utils.forEach(params, function serialize(val, key) {
31 | if (val === null || typeof val === 'undefined') {
32 | return
33 | }
34 |
35 | if (utils.isArray(val)) {
36 | key = key + '[]'
37 | } else {
38 | val = [val]
39 | }
40 |
41 | utils.forEach(val, function parseValue(v) {
42 | if (utils.isDate(v)) {
43 | v = v.toISOString()
44 | } else if (utils.isObject(v)) {
45 | v = JSON.stringify(v)
46 | }
47 | parts.push(encode(key) + '=' + encode(v))
48 | })
49 | })
50 |
51 | serializedParams = parts.join('&')
52 | }
53 |
54 | if (serializedParams) {
55 | var hashmarkIndex = url.indexOf('#')
56 | if (hashmarkIndex !== -1) {
57 | url = url.slice(0, hashmarkIndex)
58 | }
59 |
60 | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
61 | }
62 |
63 | return url
64 | }
65 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/helpers/buildURL.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import * as utils from './../utils'
4 |
5 | function encode(val) {
6 | return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']')
7 | }
8 |
9 | /**
10 | * Build a URL by appending params to the end
11 | *
12 | * @param {string} url The base of the url (e.g., http://www.google.com)
13 | * @param {object} [params] The params to be appended
14 | * @returns {string} The formatted url
15 | */
16 | export default function buildURL(url, params, paramsSerializer) {
17 | /*eslint no-param-reassign:0*/
18 | if (!params) {
19 | return url
20 | }
21 |
22 | var serializedParams
23 | if (paramsSerializer) {
24 | serializedParams = paramsSerializer(params)
25 | } else if (utils.isURLSearchParams(params)) {
26 | serializedParams = params.toString()
27 | } else {
28 | var parts = []
29 |
30 | utils.forEach(params, function serialize(val, key) {
31 | if (val === null || typeof val === 'undefined') {
32 | return
33 | }
34 |
35 | if (utils.isArray(val)) {
36 | key = key + '[]'
37 | } else {
38 | val = [val]
39 | }
40 |
41 | utils.forEach(val, function parseValue(v) {
42 | if (utils.isDate(v)) {
43 | v = v.toISOString()
44 | } else if (utils.isObject(v)) {
45 | v = JSON.stringify(v)
46 | }
47 | parts.push(encode(key) + '=' + encode(v))
48 | })
49 | })
50 |
51 | serializedParams = parts.join('&')
52 | }
53 |
54 | if (serializedParams) {
55 | var hashmarkIndex = url.indexOf('#')
56 | if (hashmarkIndex !== -1) {
57 | url = url.slice(0, hashmarkIndex)
58 | }
59 |
60 | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
61 | }
62 |
63 | return url
64 | }
65 |
--------------------------------------------------------------------------------
/test/dev-test/uni.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * 这里是uni-app内置的常用样式变量
3 | *
4 | * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
5 | * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
6 | *
7 | */
8 |
9 | /**
10 | * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
11 | *
12 | * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
13 | */
14 |
15 | /* 颜色变量 */
16 |
17 | /* 行为相关颜色 */
18 | $uni-color-primary: #007aff;
19 | $uni-color-success: #4cd964;
20 | $uni-color-warning: #f0ad4e;
21 | $uni-color-error: #dd524d;
22 |
23 | /* 文字基本颜色 */
24 | $uni-text-color:#333;//基本色
25 | $uni-text-color-inverse:#fff;//反色
26 | $uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
27 | $uni-text-color-placeholder: #808080;
28 | $uni-text-color-disable:#c0c0c0;
29 |
30 | /* 背景颜色 */
31 | $uni-bg-color:#ffffff;
32 | $uni-bg-color-grey:#f8f8f8;
33 | $uni-bg-color-hover:#f1f1f1;//点击状态颜色
34 | $uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
35 |
36 | /* 边框颜色 */
37 | $uni-border-color:#c8c7cc;
38 |
39 | /* 尺寸变量 */
40 |
41 | /* 文字尺寸 */
42 | $uni-font-size-sm:24rpx;
43 | $uni-font-size-base:28rpx;
44 | $uni-font-size-lg:32rpx;
45 |
46 | /* 图片尺寸 */
47 | $uni-img-size-sm:40rpx;
48 | $uni-img-size-base:52rpx;
49 | $uni-img-size-lg:80rpx;
50 |
51 | /* Border Radius */
52 | $uni-border-radius-sm: 4rpx;
53 | $uni-border-radius-base: 6rpx;
54 | $uni-border-radius-lg: 12rpx;
55 | $uni-border-radius-circle: 50%;
56 |
57 | /* 水平间距 */
58 | $uni-spacing-row-sm: 10px;
59 | $uni-spacing-row-base: 20rpx;
60 | $uni-spacing-row-lg: 30rpx;
61 |
62 | /* 垂直间距 */
63 | $uni-spacing-col-sm: 8rpx;
64 | $uni-spacing-col-base: 16rpx;
65 | $uni-spacing-col-lg: 24rpx;
66 |
67 | /* 透明度 */
68 | $uni-opacity-disabled: 0.3; // 组件禁用态的透明度
69 |
70 | /* 文章场景相关 */
71 | $uni-color-title: #2C405A; // 文章标题颜色
72 | $uni-font-size-title:40rpx;
73 | $uni-color-subtitle: #555555; // 二级标题颜色
74 | $uni-font-size-subtitle:36rpx;
75 | $uni-color-paragraph: #3F536E; // 文章段落颜色
76 | $uni-font-size-paragraph:30rpx;
--------------------------------------------------------------------------------
/example/request-demo/uni.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * 这里是uni-app内置的常用样式变量
3 | *
4 | * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
5 | * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
6 | *
7 | */
8 |
9 | /**
10 | * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
11 | *
12 | * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
13 | */
14 |
15 | /* 颜色变量 */
16 |
17 | /* 行为相关颜色 */
18 | $uni-color-primary: #007aff;
19 | $uni-color-success: #4cd964;
20 | $uni-color-warning: #f0ad4e;
21 | $uni-color-error: #dd524d;
22 |
23 | /* 文字基本颜色 */
24 | $uni-text-color:#333;//基本色
25 | $uni-text-color-inverse:#fff;//反色
26 | $uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
27 | $uni-text-color-placeholder: #808080;
28 | $uni-text-color-disable:#c0c0c0;
29 |
30 | /* 背景颜色 */
31 | $uni-bg-color:#ffffff;
32 | $uni-bg-color-grey:#f8f8f8;
33 | $uni-bg-color-hover:#f1f1f1;//点击状态颜色
34 | $uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
35 |
36 | /* 边框颜色 */
37 | $uni-border-color:#c8c7cc;
38 |
39 | /* 尺寸变量 */
40 |
41 | /* 文字尺寸 */
42 | $uni-font-size-sm:24upx;
43 | $uni-font-size-base:28upx;
44 | $uni-font-size-lg:32upx;
45 |
46 | /* 图片尺寸 */
47 | $uni-img-size-sm:40upx;
48 | $uni-img-size-base:52upx;
49 | $uni-img-size-lg:80upx;
50 |
51 | /* Border Radius */
52 | $uni-border-radius-sm: 4upx;
53 | $uni-border-radius-base: 6upx;
54 | $uni-border-radius-lg: 12upx;
55 | $uni-border-radius-circle: 50%;
56 |
57 | /* 水平间距 */
58 | $uni-spacing-row-sm: 10px;
59 | $uni-spacing-row-base: 20upx;
60 | $uni-spacing-row-lg: 30upx;
61 |
62 | /* 垂直间距 */
63 | $uni-spacing-col-sm: 8upx;
64 | $uni-spacing-col-base: 16upx;
65 | $uni-spacing-col-lg: 24upx;
66 |
67 | /* 透明度 */
68 | $uni-opacity-disabled: 0.3; // 组件禁用态的透明度
69 |
70 | /* 文章场景相关 */
71 | $uni-color-title: #2C405A; // 文章标题颜色
72 | $uni-font-size-title:40upx;
73 | $uni-color-subtitle: #555555; // 二级标题颜色
74 | $uni-font-size-subtitle:36upx;
75 | $uni-color-paragraph: #3F536E; // 文章段落颜色
76 | $uni-font-size-paragraph:30upx;
--------------------------------------------------------------------------------
/example/request-demo/pages/goods-list/goods-list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | luch-request:
8 | luch-request官网
9 |
10 |
11 | 我的博客:
12 | luch的博客
13 |
14 |
15 |
16 |
17 |
18 |
65 |
66 |
92 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: /assets/img/logo.jpg
4 | heroText: luch-request
5 | tagline: 基于Promise开发的uni-app跨平台请求库
6 | actionText: 快速上手 →
7 | actionLink: /handbook/
8 | features:
9 | - title: 项目级别
10 | details: 更小的体积,易用的api,方便的自定义能力。
11 | - title: 稳定维护
12 | details: luch-request 至今已至少有17个版本的迭代。下载次数超1W。
13 | - title: 代码简洁
14 | details: 插件使用es6,es7 开发,使代码的可读性很高,源码清晰明了。
15 | - title: 条件编译
16 | details: 插件开发使用了`条件编译`避免了不同终端可能产生的冗余代码。
17 | - title: 规范
18 | details: eslint、rollup等构建工具辅助开发。
19 | - title: 方便简单的自定义能力
20 | details: 有` custom ` 自定义参数的支持,满足你所有的自定义要求。
21 | footer: MIT Licensed | Copyright © 2020-2023 quanzhan.co
22 | ---
23 |
24 |
25 | 友情链接
26 |
27 |
34 |
37 |
38 |
78 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | // import resolve from 'rollup-plugin-node-resolve'
2 | // import babel from 'rollup-plugin-babel'
3 | // import json from 'rollup-plugin-json'
4 | // import commonjs from 'rollup-plugin-commonjs'
5 | // import replace from 'rollup-plugin-replace'
6 | import {eslint} from 'rollup-plugin-eslint'
7 | // import {uglify} from 'rollup-plugin-uglify'
8 | // 配置服务
9 | // import liveServer from 'rollup-plugin-live-server'
10 | import copy from 'rollup-plugin-copy'
11 | // var path = require('path');
12 |
13 | // const mode = process.env.NODE_ENV
14 | // const isWatch = process.env.ROLLUP_WATCH
15 | // const zip = require('rollup-plugin-zip')
16 |
17 | // console.log('执行环境:', mode)
18 |
19 | // const isProd = mode === 'production'
20 |
21 | export default {
22 | input: 'src/lib/luch-request.js',
23 | output: {
24 | file: 'dist/index.js',
25 | format: 'umd',
26 | name: 'LuChRequest',
27 | globals: {},
28 | sourcemap: true
29 | },
30 | external: [],
31 | plugins: [
32 | // json(),
33 | eslint(),
34 | // replace({
35 | // 'process.env.NODE_ENV': JSON.stringify(mode)
36 | // }),
37 | // resolve(),
38 | // babel({
39 | // runtimeHelpers: true,
40 | // exclude : ['node_modules/**']
41 | // }),
42 | // commonjs(),
43 | // isWatch && liveServer({
44 | // port: 3000,
45 | // root: 'test',
46 | // file: 'index.html',
47 | // open: false,
48 | // wait: 500
49 | // }),
50 | // isProd && uglify({
51 | // // comments: ['all'],
52 | // output: {
53 | // // 最紧凑的输出
54 | // // beautify: false,
55 | // // 删除所有的注释
56 | // // comments: ['all'],
57 | // },
58 | // warnings: false,
59 | // compress: {
60 | // // comments: ['all'],
61 | // pure_getters: true,
62 | // unsafe: true,
63 | // unsafe_comps: true,
64 | // }
65 | // })
66 | copy({
67 | targets: [
68 | {src: ['src/lib/utils.js', 'src/lib/core', 'src/lib/helpers', 'src/lib/utils', 'src/lib/adapters'], dest: 'DCloud/luch-request'},
69 | {src: 'src/lib/luch-request.js', dest: 'DCloud/luch-request', rename: 'index.js'},
70 | {src: 'src/lib/luch-request.d.ts', dest: 'DCloud/luch-request', rename: 'index.d.ts'},
71 | {src: ['example/request-demo'], dest: 'DCloud/'},
72 | ]
73 | }),
74 | // zip({
75 | // file: 'DCloud/luch-request.zip',
76 | // dir: './DCloud/luch-request'
77 | // })
78 | ]
79 | }
80 |
--------------------------------------------------------------------------------
/history.md:
--------------------------------------------------------------------------------
1 | ## [3.1.1](https://github.com/lei-mu/luch-request/compare/3.1.0-alpha.0...3.1.1) (2023-08-02)
2 |
3 |
4 |
5 |
6 | ## [3.1.0](https://github.com/lei-mu/luch-request/compare/3.0.8...3.1.0) (2023-05-25)
7 |
8 |
9 | ### Features
10 |
11 | * 更新请求新配置项。新增‘是否尝试将响应数据json化’配置项。 ([68344a1](https://github.com/lei-mu/luch-request/commit/68344a1d9dcbf586d4a0aff37d02aa0bb27ff45c)), closes [#113](https://github.com/lei-mu/luch-request/issues/113)
12 | * 增加`version` 属性,获取插件版本号 ([40403d2](https://github.com/lei-mu/luch-request/commit/40403d2ef57dead0f577a384ac686cc7dcc772da))
13 |
14 |
15 |
16 |
17 | ## [3.0.8](https://github.com/lei-mu/luch-request/compare/3.0.7...3.0.8) (2022-08-23)
18 |
19 |
20 | ### Features
21 |
22 | * `put` 方法增加快手小程序和京东小程序的支持 ([7e15dff](https://github.com/lei-mu/luch-request/commit/7e15dff0ac343ccbd6a298c7c9ae8ef0e2148eb9))
23 | * 参考axio源代码 添加支持paramsSerializer。 ([cae1043](https://github.com/lei-mu/luch-request/commit/cae10430dc7222d85e0cadb13512898d66998547))
24 | * 返回数据增加`rawData`,保留返回的原始数据 ([3924b7c](https://github.com/lei-mu/luch-request/commit/3924b7c3ea444526be436a31f9e7d5623749580b))
25 | * 局部请求配置支持baseURL ([df2d98f](https://github.com/lei-mu/luch-request/commit/df2d98fc063f356ffd525158e9cd47d7eb24f68f))
26 |
27 |
28 |
29 |
30 | ## 3.0.7 (2021-09-04)
31 |
32 | 1. Bug Fix: 修复通过 `Request.config` 设置全局参数,多个实例`config`存在共同引用bug
33 |
34 |
35 | ## 3.0.6 (2021-05-10)
36 |
37 | 1. New Feature: APP端 增加`responseType`配置项
38 |
39 | ## 3.0.5 (2021-01-10)
40 | ### Features
41 |
42 | * [重要] APP不再支持`CONNECT`、`HEAD`、`TRACE`请求方式。[uni.request](https://uniapp.dcloud.io/api/request/request)
43 | * [重要]全局默认`timeout`由`30000`ms,改为`60000`ms
44 | * [重要]增加`index.d.ts`文件支持。感谢`Mr_Mao`的支持。github:`https://github.com/TuiMao233`
45 | * [重要]网络请求相关接口 uni.request、uni.uploadFile、uni.downloadFile 支持 timeout 参数。
46 | * [重要]返回结果response 增加`fullPath`参数。
47 |
48 | ## 3.0.4 (2020-07-05)
49 |
50 | 1. New Feature: request 方法增加 ` firstIpv4 `配置项
51 | 1. New Feature: 增加 ` middleware `通用请求方法
52 |
53 | ## 3.0.3 (2020-06-16)
54 |
55 | 1. Bug Fix: 修复` params ` 选项对数组格式化错误bug
56 |
57 | ## 3.0.2 (2020-06-04)
58 |
59 | 1. Bug Fix: 修复文件上传和request 配置缺少字段bug
60 |
61 | ## 3.0.1 (2020-06-02)
62 |
63 | 1. Bug Fix: 请求方式都为` GET `的bug
64 |
65 | ## 3.0.0 (2020-06-01)
66 |
67 | 1. New Feature: 支持多拦截器
68 | 1. New Feature: 支持局部配置自定义验证器
69 |
70 | ## 2.0.1 (2020-05-01)
71 |
72 | 1. Bug Fix: 修复多实例全局配置共用问题
73 |
74 | ## 2.0.0 (2020-04-24)
75 |
76 | 1. New Feature: 增加 request ` withCredentials `选项(仅h5端支持)
77 | 1. New Feature: h5端 upload 增加 ` files ` ` file `选项。[uni.uploadFile](https://uniapp.dcloud.io/api/request/network-file?id=uploadfile "uni.uploadFile")
78 | 1. Enhancement: ` params ` 选项参数格式化方法使用axios 格式化方法
79 | 1. Bug Fix: 对upload 返回data 为空字符串的情况容错
80 | 1. Change: 修改header与全局合并方式。当前:header = Object.assign(全局,局部)
81 |
82 | ## 0.0.0 (2019-05)
83 |
84 | 1. luch-request created
85 |
86 |
87 |
--------------------------------------------------------------------------------
/docs/issue/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar: auto
3 | title: 常见问题
4 | ---
5 |
6 | # 常见问题
7 |
8 | ## 如果cli 用户npm 引入报错?
9 |
10 | 插件使用es6,es7 开发,好处就是结构清晰,语义化,开发代码少,并且对于目前的我来说,完全没有必要使用es5开发。
11 |
12 | 为什么不用babel解决:babel 编译后的代码对uni的条件编译注释不友好。如果不用条件编译则不能发挥最大优势。
13 |
14 | 这样存在的问题:对于HBuilderX 创建的项目完全没有影响,idea 会对node_modules 里的插件条件编译,并且babel。主要是cli 用户,cli 不会对node_modules 里的代码babel。
15 |
16 | 可尝试如下配置
17 | ``` javascript
18 | // vue.config.js
19 | module.exports = {
20 | transpileDependencies: ['luch-request']
21 | }
22 | ```
23 |
24 |
25 | ## 为什么会请求两次?
26 |
27 | 如果其中有`options` 请求:`本地访问接口时跨域请求,所以浏览器会先发一个option 去预测能否成功,然后再发一个真正的请求`。(自己观察请求头,Request Method,百度`简单请求`)
28 |
29 | ## 如何跨域?
30 |
31 | 问的人不少,可以先百度了解一下。如何跨域
32 |
33 | ## `TypeError: undefined is not an object (evaluating 'this.$http.get')`
34 |
35 | 不知道为啥问的人这么多?太基础了,百度学习一下 export default 和export,头大。
36 | `import { http } from '@/utils/luch-request/index.js'`
37 |
38 | ## 什么参数需要在` setConfig ` 设置?什么参数需要在` request ` 拦截器设置?
39 |
40 | - ` setConfig ` 适用于设置一些静态的/默认的参数;比如header 里的一些默认值、默认全局参数(全局请求配置)。` token ` 并不适合在这里设置。
41 | - ` interceptors.request ` 拦截器适用范围较广,但我仍然建议把一些静态的东西放在 ` setConfig ` 里。拦截器会在每次请求调用,而 ` setConfig ` 仅在调用时修改一遍。
42 |
43 | ## 如何jwt无痛刷新?
44 |
45 | [jwt无痛刷新](/resources/article.html#jwt-%E6%97%A0%E7%97%9B%E5%88%B7%E6%96%B0)
46 |
47 | ## 如何配置超时时间?
48 |
49 | **全局**
50 |
51 | 网络请求的 超时时间 可以统一在 manifest.json 中配置 [networkTimeout](https://uniapp.dcloud.io/collocation/manifest?id=networktimeout)
52 |
53 | 插件的全局配置超时时间:[插件-全局请求配置-timeout](/guide/3.x/#%E5%8F%AF%E9%85%8D%E7%BD%AE%E9%A1%B9)。必须请求方法和终端支持`timeout`,支持度参照[timeout 支持度](/guide/3.x/#middleware)
54 |
55 | **局部**
56 |
57 | 局部配置项`timeout`:[timeout](/guide/3.x/#request)。必须请求方法和终端支持`timeout`,支持度参照[timeout 支持度](/guide/3.x/#middleware)
58 |
59 | 如果终端和请求方式不支持`timeout`,可参考如下实现
60 | ```` javascript
61 | http.request({
62 | method: 'POST', // 请求方法必须大写 [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE]
63 | url: '/user/12345',
64 | data: {
65 | firstName: 'Fred',
66 | lastName: 'Flintstone'
67 | },
68 | params: { // 会拼接到url上
69 | token: '1111'
70 | },
71 | // 返回当前请求的task, options。请勿在此处修改options。非必填
72 | getTask: (task, options) => {
73 | // 500ms 后终止请求
74 | setTimeout(() => {
75 | task.abort()
76 | }, 500)
77 | }
78 | })
79 | ````
80 |
81 | ## 发送FormData?
82 |
83 | uni 不支持发送`FormData`对象
84 |
85 | 对于 POST 方法且 header['content-type'] 为 application/json 的数据,会进行 JSON 序列化。
86 |
87 | 对于 POST 方法且 header['content-type'] 为 application/x-www-form-urlencoded 的数据,会将数据转换为 query string。
88 |
89 | 所以,如果你想发送formData 类型数据,请将`header['content-type']` 设置为 `application/x-www-form-urlencoded`。
90 |
91 | 如果你的formData 里有`file` 怎么办?请使用插件的[upload](/guide/3.x/#upload)方法。
92 |
93 |
94 |
95 | ## 后台返回bigInt类型处理?
96 | `3.0.8`版本给`response` 新增 `rawData` 字段,保存原始数据。请在拦截器自定义处理该字段。或者局部处理。
--------------------------------------------------------------------------------
/example/request-demo/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name" : "request-demo",
3 | "appid" : "",
4 | "description": "",
5 | "versionName": "1.0.0",
6 | "versionCode": "100",
7 | "transformPx": false,
8 | /* 5+App特有相关 */
9 | "app-plus": {
10 | "usingComponents": true,
11 | "splashscreen": {
12 | "alwaysShowBeforeRender": true,
13 | "waiting": true,
14 | "autoclose": true,
15 | "delay": 0
16 | },
17 | /* 模块配置 */
18 | "modules": {
19 |
20 | },
21 | /* 应用发布信息 */
22 | "distribute": {
23 | /* android打包配置 */
24 | "android": {
25 | "permissions": ["",
26 | "",
27 | "",
28 | "",
29 | "",
30 | "",
31 | "",
32 | "",
33 | "",
34 | "",
35 | "",
36 | "",
37 | "",
38 | "",
39 | "",
40 | "",
41 | "",
42 | "",
43 | "",
44 | "",
45 | "",
46 | ""
47 | ]
48 | },
49 | /* ios打包配置 */
50 | "ios": {
51 |
52 | },
53 | /* SDK配置 */
54 | "sdkConfigs": {
55 |
56 | }
57 | }
58 | },
59 | /* 快应用特有相关 */
60 | "quickapp": {
61 |
62 | },
63 | /* 小程序特有相关 */
64 | "mp-weixin": {
65 | "appid": "",
66 | "setting": {
67 | "urlCheck": false
68 | },
69 | "usingComponents": true
70 | },
71 | "mp-alipay" : {
72 | "usingComponents" : true
73 | },
74 | "mp-baidu" : {
75 | "usingComponents" : true
76 | },
77 | "mp-toutiao" : {
78 | "usingComponents" : true
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/test/dev-test/api/service.js:
--------------------------------------------------------------------------------
1 |
2 | import Request from '@/utils/luch-request/index.js'
3 |
4 |
5 | const getTokenStorage = () => {
6 | let token = ''
7 | try {
8 | token = uni.getStorageSync('token')
9 | } catch (e) {
10 | //TODO handle the exception
11 | }
12 | return token
13 | }
14 |
15 | const test = new Request()
16 | /**
17 | * 修改全局配置示例
18 | const test = new Request({
19 | header: {a:1}, // 举例
20 | baseURL: 'https://www.fastmock.site/mock/26243bdf9062eeae2848fc67603bda2d/luchrequest',
21 | validateStatus: (statusCode) => { // statusCode 必存在。此处示例为全局默认配置
22 | return statusCode >= 200 && statusCode < 300
23 | }
24 | })
25 | test.config.baseURL = 'https://www.fastmock.site/mock/26243bdf9062eeae2848fc67603bda2d/luchrequest'
26 | **/
27 |
28 | test.setConfig((config) => { /* 设置全局配置 */
29 | config.baseURL = 'https://www.fastmock.site/mock/26243bdf9062eeae2848fc67603bda2d/luchrequest'
30 | config.header = {
31 | ...config.header,
32 | a: 1, // 演示
33 | b: 2 // 演示
34 | }
35 | return config
36 | })
37 |
38 | test.interceptors.request.use((config) => { /* 请求之前拦截器。可以使用async await 做异步操作 */
39 | config.header = {
40 | ...config.header,
41 | a: 3 // 演示
42 | }
43 | /*
44 | if (!token) { // 如果token不存在,return Promise.reject(config) 会取消本次请求
45 | return Promise.reject(config)
46 | }
47 | */
48 | return config
49 | }, (config) => {
50 | return Promise.reject(config)
51 | })
52 |
53 |
54 | test.interceptors.response.use((response) => { /* 请求之后拦截器。可以使用async await 做异步操作 */
55 | if (response.data.code !== 200) { // 服务端返回的状态码不等于200,则reject()
56 | return Promise.reject(response)
57 | }
58 | return response
59 | }, (response) => { // 请求错误做点什么。可以使用async await 做异步操作
60 | return Promise.reject(response)
61 | })
62 |
63 |
64 | const http = new Request()
65 | http.setConfig((config) => { /* 设置全局配置 */
66 | config.baseURL = 'https://www.fastmock.site/mock/26243bdf9062eeae2848fc67603bda2d/luchrequest' /* 根域名不同 */
67 | config.header = {
68 | ...config.header,
69 | a: 1, // 演示
70 | b: 2 // 演示
71 | }
72 | console.log('全局默认config');
73 | console.log(config);
74 | return config
75 | })
76 |
77 |
78 | http.interceptors.request.use((config) => { /* 请求之前拦截器。可以使用async await 做异步操作 */
79 | config.header = {
80 | ...config.header,
81 | token: getTokenStorage()
82 | }
83 | /*
84 | if (!token) { // 如果token不存在,return Promise.reject(config) 会取消本次请求
85 | return Promise.reject(config)
86 | }
87 | */
88 | return config
89 | }, (config) => {
90 | return Promise.reject(config)
91 | })
92 |
93 | // 必须使用异步函数,注意
94 | http.interceptors.response.use(async (response) => { /* 请求之后拦截器。可以使用async await 做异步操作 */
95 | // if (response.data.code !== 200) { // 服务端返回的状态码不等于200,则reject()
96 | // return Promise.reject(response)
97 | // }
98 | return response
99 | }, (response) => { // 请求错误做点什么。可以使用async await 做异步操作
100 | console.log(response)
101 | return Promise.reject(response)
102 | })
103 |
104 | export {
105 | http,
106 | test
107 | }
108 |
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | locales: {
3 | '/': {
4 | lang: 'zh-CN',
5 | title: 'luch-request',
6 | description: 'luch-request 是一个基于Promise开发的uni-app跨平台、项目级别的请求库,它有更小的体积,易用的api,方便简单的自定义能力。luch-request官网,luch的博客,uni-app,request插件,uni request封装,uni request插件'
7 | }
8 | },
9 | base: '/luch-request/',
10 | title: 'luch-request',
11 | description: 'luch-request 是一个基于Promise开发的uni-app跨平台、项目级别的请求库,它有更小的体积,易用的api,方便简单的自定义能力。luch-request官网,luch的博客,uni-app,request插件,uni request封装,uni request插件',
12 | head: [
13 | ['meta', {'http-equiv': 'X-UA-Compatible', content: 'IE=Edge'}],
14 | ['meta', {'name': 'renderer', content: 'webkit'}],
15 | ['meta', {'name': 'author', content: 'luch'}],
16 | ['meta', {'name': 'keywords', content: 'luch,luch-requst,luch-request官网,luch的个人博客,uni-app,request插件,uni request封装,uni request插件'}],
17 | ['script', {}, `
18 | var _hmt = _hmt || [];
19 | (function() {
20 | var hm = document.createElement("script");
21 | hm.src = "https://hm.baidu.com/hm.js?d64f5f90a8b778dcc6ae876318d0b091";
22 | var s = document.getElementsByTagName("script")[0];
23 | s.parentNode.insertBefore(hm, s);
24 | })();
25 | `]
26 | ],
27 | themeConfig: {
28 | // 假定是 GitHub. 同时也可以是一个完整的 GitLab URL
29 | repo: 'https://github.com/lei-mu/luch-request',
30 | // 自定义仓库链接文字。默认从 `themeConfig.repo` 中自动推断为
31 | // "GitHub"/"GitLab"/"Bitbucket" 其中之一,或是 "Source"。
32 | // repoLabel: '查看源码',
33 |
34 | // 以下为可选的编辑链接选项
35 | // 假如文档不是放在仓库的根目录下:
36 | docsDir: 'docs',
37 | // 假如文档放在一个特定的分支下:
38 | docsBranch: 'docs',
39 | // 默认是 false, 设置为 true 来启用
40 | editLinks: true,
41 | // 默认为 "Edit this page"
42 | editLinkText: '帮助我改善此页面!',
43 | nav: [
44 | {text: '首页', link: '/'},
45 | {
46 | text: '文档',
47 | ariaLabel: '文档',
48 | items: [
49 | {text: '3.x文档', link: '/guide/3.x/'},
50 | {text: '2.x文档', link: '/guide/2.x/'},
51 | ]
52 | },
53 | {text: '指南', link: '/handbook/'},
54 | {text: '常见问题', link: '/issue/'},
55 | {text: '更新记录', link: 'https://github.com/lei-mu/luch-request/releases', target: '_blank', rel: 'nofollow noopener noreferrer'},
56 | {
57 | text: '相关资源',
58 | ariaLabel: '相关资源',
59 | items: [
60 | {text: '相关文章', link: '/resources/article'}
61 | ]
62 | },
63 | {text: '鸣谢', link: '/acknowledgement/'},
64 | {text: '博客', link: 'https://www.quanzhan.co/', target: '_blank'},
65 | {
66 | text: 'DCloud',
67 | ariaLabel: 'DCloud',
68 | items: [
69 | {text: '插件市场', link: 'https://ext.dcloud.net.cn/plugin?id=392', target: '_blank', rel: 'nofollow noopener noreferrer'},
70 | {text: '社区', link: 'https://ask.dcloud.net.cn/question/74922', target: '_blank', rel: 'nofollow noopener noreferrer'}
71 | ]
72 | }
73 | ],
74 | lastUpdated: 'Last Updated',
75 | },
76 | plugins: [
77 | ['@vuepress/pwa',{
78 | serviceWorker: true,
79 | updatePopup: {
80 | message: '此文档有新的内容', // defaults to 'New content is available.'
81 | buttonText: '更新' // defaults to 'Refresh'
82 | }
83 | }],
84 | '@vuepress/active-header-links'
85 | ],
86 | smoothScroll: true
87 | }
88 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "luch-request",
3 | "version": "3.1.1",
4 | "description": "基于Promise实现uni-app request 请求插件",
5 | "keywords": [
6 | "uni-app",
7 | "request",
8 | "Promise",
9 | "luch",
10 | "luch-request"
11 | ],
12 | "main": "src/lib/luch-request.js",
13 | "scripts": {
14 | "dev": "rollup -c",
15 | "watch": "rollup -c -w",
16 | "build": "rimraf DCloud && rollup -c --environment NODE_ENV:production",
17 | "zipD": "node node/zipDCloudPlugin.js && node node/zipDCloudDemo.js",
18 | "docs": "vuepress dev docs",
19 | "docs:build": "vuepress build docs",
20 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -w -r 0",
21 | "pub": "npm publish && cnpm sync luch-request",
22 | "pub:alpha": "npm publish --tag=alpha && cnpm sync luch-request",
23 | "test": "echo \"Error: no test specified\" && exit 1"
24 | },
25 | "repository": {
26 | "type": "git",
27 | "url": "https://github.com/lei-mu/luch-request.git"
28 | },
29 | "author": "luch",
30 | "license": "MIT",
31 | "bugs": {
32 | "url": "https://github.com/lei-mu/luch-request/issues"
33 | },
34 | "homepage": "https://www.quanzhan.co/luch-request/",
35 | "devDependencies": {
36 | "@babel/core": "^7.9.0",
37 | "@babel/plugin-proposal-class-properties": "^7.8.3",
38 | "@babel/plugin-transform-arrow-functions": "^7.8.3",
39 | "@babel/preset-env": "^7.9.5",
40 | "@vuepress/plugin-active-header-links": "^1.5.0",
41 | "@vuepress/plugin-pwa": "^1.5.2",
42 | "archiver": "^4.0.1",
43 | "babel-eslint": "^10.1.0",
44 | "babel-preset-es2015": "^6.24.1",
45 | "commitizen": "^4.2.4",
46 | "conventional-changelog-cli": "^2.1.1",
47 | "cz-conventional-changelog": "^3.2.0",
48 | "eslint": "^6.8.0",
49 | "grunt": "^1.1.0",
50 | "grunt-babel": "^8.0.0",
51 | "load-grunt-tasks": "^5.1.0",
52 | "node-zip": "^1.1.1",
53 | "rollup": "^2.66.1",
54 | "rollup-plugin-babel": "^4.4.0",
55 | "rollup-plugin-commonjs": "^10.1.0",
56 | "rollup-plugin-copy": "^3.3.0",
57 | "rollup-plugin-eslint": "^7.0.0",
58 | "rollup-plugin-json": "^4.0.0",
59 | "rollup-plugin-live-server": "^1.0.3",
60 | "rollup-plugin-node-resolve": "^5.2.0",
61 | "rollup-plugin-replace": "^2.2.0",
62 | "rollup-plugin-uglify": "^6.0.4",
63 | "rollup-plugin-zip": "^1.0.0",
64 | "validate-commit-msg": "^2.14.0",
65 | "vuepress": "^1.4.1"
66 | },
67 | "engines": {
68 | },
69 | "config": {
70 | "commitizen": {
71 | "path": "./node_modules/cz-conventional-changelog"
72 | },
73 | "ghooks": {
74 | "commit-msg": "validate-commit-msg"
75 | },
76 | "validate-commit-msg": {
77 | "types": [
78 | "feat",
79 | "fix",
80 | "docs",
81 | "style",
82 | "refactor",
83 | "perf",
84 | "test",
85 | "build",
86 | "ci",
87 | "chore",
88 | "revert"
89 | ],
90 | "scope": {
91 | "required": false,
92 | "allowed": [
93 | "*"
94 | ],
95 | "validate": false,
96 | "multiple": false
97 | },
98 | "warnOnFail": false,
99 | "maxSubjectLength": 100,
100 | "subjectPattern": ".+",
101 | "subjectPatternErrorMsg": "subject does not match subject pattern!",
102 | "helpMessage": "",
103 | "autoFix": false
104 | }
105 | },
106 | "dependencies": {
107 | "@dcloudio/types": "^2.0.16"
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/test/dev-test/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name" : "dev-test",
3 | "appid" : "__UNI__7E67B0A",
4 | "description" : "",
5 | "versionName" : "1.0.0",
6 | "versionCode" : "100",
7 | "transformPx" : false,
8 | /* 5+App特有相关 */
9 | "app-plus" : {
10 | "usingComponents" : true,
11 | "nvueCompiler" : "uni-app",
12 | "compilerVersion" : 3,
13 | "splashscreen" : {
14 | "alwaysShowBeforeRender" : true,
15 | "waiting" : true,
16 | "autoclose" : true,
17 | "delay" : 0
18 | },
19 | /* 模块配置 */
20 | "modules" : {},
21 | /* 应用发布信息 */
22 | "distribute" : {
23 | /* android打包配置 */
24 | "android" : {
25 | "permissions" : [
26 | "",
27 | "",
28 | "",
29 | "",
30 | "",
31 | "",
32 | "",
33 | "",
34 | "",
35 | "",
36 | "",
37 | "",
38 | "",
39 | "",
40 | "",
41 | "",
42 | "",
43 | "",
44 | "",
45 | "",
46 | "",
47 | ""
48 | ]
49 | },
50 | /* ios打包配置 */
51 | "ios" : {},
52 | /* SDK配置 */
53 | "sdkConfigs" : {}
54 | }
55 | },
56 | /* 快应用特有相关 */
57 | "quickapp" : {},
58 | /* 小程序特有相关 */
59 | "mp-weixin" : {
60 | "appid" : "",
61 | "setting" : {
62 | "urlCheck" : false
63 | },
64 | "usingComponents" : true
65 | },
66 | "mp-alipay" : {
67 | "usingComponents" : true
68 | },
69 | "mp-baidu" : {
70 | "usingComponents" : true
71 | },
72 | "mp-toutiao" : {
73 | "usingComponents" : true
74 | },
75 | "uniStatistics": {
76 | "enable": false
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/example/request-demo/api/service.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @version 3.0.5
3 | * @Author lu-ch
4 | * @Email webwork.s@qq.com
5 | * 文档: https://www.quanzhan.co/luch-request/
6 | * github: https://github.com/lei-mu/luch-request
7 | * DCloud: http://ext.dcloud.net.cn/plugin?id=392
8 | * HBuilderX: beat-3.0.4 alpha-3.0.4
9 | */
10 |
11 | import Request from '@/utils/luch-request/index.js'
12 |
13 |
14 | const getTokenStorage = () => {
15 | let token = ''
16 | try {
17 | token = uni.getStorageSync('token')
18 | } catch (e) {
19 | }
20 | return token
21 | }
22 |
23 | const test = new Request()
24 | /**
25 | * 修改全局配置示例
26 | const test = new Request({
27 | header: {a:1}, // 举例
28 | baseURL: 'https://www.fastmock.site/mock/26243bdf9062eeae2848fc67603bda2d/luchrequest',
29 | validateStatus: (statusCode) => { // statusCode 必存在。此处示例为全局默认配置
30 | return statusCode >= 200 && statusCode < 300
31 | }
32 | })
33 | test.config.baseURL = 'https://www.fastmock.site/mock/26243bdf9062eeae2848fc67603bda2d/luchrequest'
34 | **/
35 | console.log(`test 请求实例的插件版本为:${test.version}`)
36 | test.setConfig((config) => { /* 设置全局配置 */
37 | config.baseURL = 'https://www.fastmock.site/mock/26243bdf9062eeae2848fc67603bda2d/luchrequest'
38 | config.header = {
39 | ...config.header,
40 | a: 1, // 演示
41 | b: 2 // 演示
42 | }
43 | config.custom = {
44 | // auth: false, // 是否传token
45 | // loading: false // 是否使用loading
46 | }
47 | return config
48 | })
49 |
50 | test.interceptors.request.use((config) => { /* 请求之前拦截器。可以使用async await 做异步操作 */
51 | config.header = {
52 | ...config.header,
53 | a: 3 // 演示
54 | }
55 | /**
56 | * custom {Object} - 自定义参数
57 | */
58 | // if (config.custom.auth) {
59 | // config.header.token = '123456'
60 | // }
61 | // if (config.custom.loading) {
62 | // uni.showLoading()
63 | // }
64 | /*
65 | if (!token) { // 如果token不存在,return Promise.reject(config) 会取消本次请求
66 | return Promise.reject(config)
67 | }
68 | */
69 | return config
70 | }, (config) => {
71 | return Promise.reject(config)
72 | })
73 |
74 |
75 | test.interceptors.response.use((response) => { /* 请求之后拦截器。可以使用async await 做异步操作 */
76 | // if (response.config.custom.loading) {
77 | // uni.hideLoading()
78 | // }
79 | if (response.data.code !== 200) { // 服务端返回的状态码不等于200,则reject()
80 | return Promise.reject(response)
81 | }
82 | return response
83 | }, (response) => { // 请求错误做点什么。可以使用async await 做异步操作
84 | // if (response.config.custom.loading) {
85 | // uni.hideLoading()
86 | // }
87 | return Promise.reject(response)
88 | })
89 |
90 |
91 | const http = new Request()
92 | http.setConfig((config) => { /* 设置全局配置 */
93 | config.baseURL = 'https://www.fastmock.site/mock/26243bdf9062eeae2848fc67603bda2d/luchrequest' /* 根域名不同 */
94 | config.header = {
95 | ...config.header,
96 | a: 1, // 演示
97 | b: 2 // 演示
98 | }
99 | return config
100 | })
101 |
102 |
103 | http.interceptors.request.use((config) => { /* 请求之前拦截器。可以使用async await 做异步操作 */
104 | config.header = {
105 | ...config.header,
106 | token: getTokenStorage()
107 | }
108 | /*
109 | if (!token) { // 如果token不存在,return Promise.reject(config) 会取消本次请求
110 | return Promise.reject(config)
111 | }
112 | */
113 | return config
114 | }, (config) => {
115 | return Promise.reject(config)
116 | })
117 |
118 |
119 | http.interceptors.response.use(async (response) => { /* 请求之后拦截器。可以使用async await 做异步操作 */
120 | // if (response.data.code !== 200) { // 服务端返回的状态码不等于200,则reject()
121 | // return Promise.reject(response)
122 | // }
123 | return response
124 | }, (response) => { // 请求错误做点什么。可以使用async await 做异步操作
125 | console.log(response)
126 | return Promise.reject(response)
127 | })
128 |
129 | export {
130 | http,
131 | test
132 | }
133 |
--------------------------------------------------------------------------------
/src/lib/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | // utils is a library of generic helper functions non-specific to axios
4 |
5 | var toString = Object.prototype.toString
6 |
7 | /**
8 | * Determine if a value is an Array
9 | *
10 | * @param {Object} val The value to test
11 | * @returns {boolean} True if value is an Array, otherwise false
12 | */
13 | export function isArray (val) {
14 | return toString.call(val) === '[object Array]'
15 | }
16 |
17 |
18 | /**
19 | * Determine if a value is an Object
20 | *
21 | * @param {Object} val The value to test
22 | * @returns {boolean} True if value is an Object, otherwise false
23 | */
24 | export function isObject (val) {
25 | return val !== null && typeof val === 'object'
26 | }
27 |
28 | /**
29 | * Determine if a value is a Date
30 | *
31 | * @param {Object} val The value to test
32 | * @returns {boolean} True if value is a Date, otherwise false
33 | */
34 | export function isDate (val) {
35 | return toString.call(val) === '[object Date]'
36 | }
37 |
38 | /**
39 | * Determine if a value is a URLSearchParams object
40 | *
41 | * @param {Object} val The value to test
42 | * @returns {boolean} True if value is a URLSearchParams object, otherwise false
43 | */
44 | export function isURLSearchParams (val) {
45 | return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
46 | }
47 |
48 |
49 | /**
50 | * Iterate over an Array or an Object invoking a function for each item.
51 | *
52 | * If `obj` is an Array callback will be called passing
53 | * the value, index, and complete array for each item.
54 | *
55 | * If 'obj' is an Object callback will be called passing
56 | * the value, key, and complete object for each property.
57 | *
58 | * @param {Object|Array} obj The object to iterate
59 | * @param {Function} fn The callback to invoke for each item
60 | */
61 | export function forEach (obj, fn) {
62 | // Don't bother if no value provided
63 | if (obj === null || typeof obj === 'undefined') {
64 | return
65 | }
66 |
67 | // Force an array if not already something iterable
68 | if (typeof obj !== 'object') {
69 | /*eslint no-param-reassign:0*/
70 | obj = [obj]
71 | }
72 |
73 | if (isArray(obj)) {
74 | // Iterate over array values
75 | for (var i = 0, l = obj.length; i < l; i++) {
76 | fn.call(null, obj[i], i, obj)
77 | }
78 | } else {
79 | // Iterate over object keys
80 | for (var key in obj) {
81 | if (Object.prototype.hasOwnProperty.call(obj, key)) {
82 | fn.call(null, obj[key], key, obj)
83 | }
84 | }
85 | }
86 | }
87 |
88 | /**
89 | * 是否为boolean 值
90 | * @param val
91 | * @returns {boolean}
92 | */
93 | export function isBoolean(val) {
94 | return typeof val === 'boolean'
95 | }
96 |
97 | /**
98 | * 是否为真正的对象{} new Object
99 | * @param {any} obj - 检测的对象
100 | * @returns {boolean}
101 | */
102 | export function isPlainObject(obj) {
103 | return Object.prototype.toString.call(obj) === '[object Object]'
104 | }
105 |
106 |
107 |
108 | /**
109 | * Function equal to merge with the difference being that no reference
110 | * to original objects is kept.
111 | *
112 | * @see merge
113 | * @param {Object} obj1 Object to merge
114 | * @returns {Object} Result of all merge properties
115 | */
116 | export function deepMerge(/* obj1, obj2, obj3, ... */) {
117 | let result = {}
118 | function assignValue(val, key) {
119 | if (typeof result[key] === 'object' && typeof val === 'object') {
120 | result[key] = deepMerge(result[key], val)
121 | } else if (typeof val === 'object') {
122 | result[key] = deepMerge({}, val)
123 | } else {
124 | result[key] = val
125 | }
126 | }
127 | for (let i = 0, l = arguments.length; i < l; i++) {
128 | forEach(arguments[i], assignValue)
129 | }
130 | return result
131 | }
132 |
133 | export function isUndefined (val) {
134 | return typeof val === 'undefined'
135 | }
136 |
--------------------------------------------------------------------------------
/DCloud/luch-request/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | // utils is a library of generic helper functions non-specific to axios
4 |
5 | var toString = Object.prototype.toString
6 |
7 | /**
8 | * Determine if a value is an Array
9 | *
10 | * @param {Object} val The value to test
11 | * @returns {boolean} True if value is an Array, otherwise false
12 | */
13 | export function isArray (val) {
14 | return toString.call(val) === '[object Array]'
15 | }
16 |
17 |
18 | /**
19 | * Determine if a value is an Object
20 | *
21 | * @param {Object} val The value to test
22 | * @returns {boolean} True if value is an Object, otherwise false
23 | */
24 | export function isObject (val) {
25 | return val !== null && typeof val === 'object'
26 | }
27 |
28 | /**
29 | * Determine if a value is a Date
30 | *
31 | * @param {Object} val The value to test
32 | * @returns {boolean} True if value is a Date, otherwise false
33 | */
34 | export function isDate (val) {
35 | return toString.call(val) === '[object Date]'
36 | }
37 |
38 | /**
39 | * Determine if a value is a URLSearchParams object
40 | *
41 | * @param {Object} val The value to test
42 | * @returns {boolean} True if value is a URLSearchParams object, otherwise false
43 | */
44 | export function isURLSearchParams (val) {
45 | return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
46 | }
47 |
48 |
49 | /**
50 | * Iterate over an Array or an Object invoking a function for each item.
51 | *
52 | * If `obj` is an Array callback will be called passing
53 | * the value, index, and complete array for each item.
54 | *
55 | * If 'obj' is an Object callback will be called passing
56 | * the value, key, and complete object for each property.
57 | *
58 | * @param {Object|Array} obj The object to iterate
59 | * @param {Function} fn The callback to invoke for each item
60 | */
61 | export function forEach (obj, fn) {
62 | // Don't bother if no value provided
63 | if (obj === null || typeof obj === 'undefined') {
64 | return
65 | }
66 |
67 | // Force an array if not already something iterable
68 | if (typeof obj !== 'object') {
69 | /*eslint no-param-reassign:0*/
70 | obj = [obj]
71 | }
72 |
73 | if (isArray(obj)) {
74 | // Iterate over array values
75 | for (var i = 0, l = obj.length; i < l; i++) {
76 | fn.call(null, obj[i], i, obj)
77 | }
78 | } else {
79 | // Iterate over object keys
80 | for (var key in obj) {
81 | if (Object.prototype.hasOwnProperty.call(obj, key)) {
82 | fn.call(null, obj[key], key, obj)
83 | }
84 | }
85 | }
86 | }
87 |
88 | /**
89 | * 是否为boolean 值
90 | * @param val
91 | * @returns {boolean}
92 | */
93 | export function isBoolean(val) {
94 | return typeof val === 'boolean'
95 | }
96 |
97 | /**
98 | * 是否为真正的对象{} new Object
99 | * @param {any} obj - 检测的对象
100 | * @returns {boolean}
101 | */
102 | export function isPlainObject(obj) {
103 | return Object.prototype.toString.call(obj) === '[object Object]'
104 | }
105 |
106 |
107 |
108 | /**
109 | * Function equal to merge with the difference being that no reference
110 | * to original objects is kept.
111 | *
112 | * @see merge
113 | * @param {Object} obj1 Object to merge
114 | * @returns {Object} Result of all merge properties
115 | */
116 | export function deepMerge(/* obj1, obj2, obj3, ... */) {
117 | let result = {}
118 | function assignValue(val, key) {
119 | if (typeof result[key] === 'object' && typeof val === 'object') {
120 | result[key] = deepMerge(result[key], val)
121 | } else if (typeof val === 'object') {
122 | result[key] = deepMerge({}, val)
123 | } else {
124 | result[key] = val
125 | }
126 | }
127 | for (let i = 0, l = arguments.length; i < l; i++) {
128 | forEach(arguments[i], assignValue)
129 | }
130 | return result
131 | }
132 |
133 | export function isUndefined (val) {
134 | return typeof val === 'undefined'
135 | }
136 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | // utils is a library of generic helper functions non-specific to axios
4 |
5 | var toString = Object.prototype.toString
6 |
7 | /**
8 | * Determine if a value is an Array
9 | *
10 | * @param {Object} val The value to test
11 | * @returns {boolean} True if value is an Array, otherwise false
12 | */
13 | export function isArray (val) {
14 | return toString.call(val) === '[object Array]'
15 | }
16 |
17 |
18 | /**
19 | * Determine if a value is an Object
20 | *
21 | * @param {Object} val The value to test
22 | * @returns {boolean} True if value is an Object, otherwise false
23 | */
24 | export function isObject (val) {
25 | return val !== null && typeof val === 'object'
26 | }
27 |
28 | /**
29 | * Determine if a value is a Date
30 | *
31 | * @param {Object} val The value to test
32 | * @returns {boolean} True if value is a Date, otherwise false
33 | */
34 | export function isDate (val) {
35 | return toString.call(val) === '[object Date]'
36 | }
37 |
38 | /**
39 | * Determine if a value is a URLSearchParams object
40 | *
41 | * @param {Object} val The value to test
42 | * @returns {boolean} True if value is a URLSearchParams object, otherwise false
43 | */
44 | export function isURLSearchParams (val) {
45 | return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
46 | }
47 |
48 |
49 | /**
50 | * Iterate over an Array or an Object invoking a function for each item.
51 | *
52 | * If `obj` is an Array callback will be called passing
53 | * the value, index, and complete array for each item.
54 | *
55 | * If 'obj' is an Object callback will be called passing
56 | * the value, key, and complete object for each property.
57 | *
58 | * @param {Object|Array} obj The object to iterate
59 | * @param {Function} fn The callback to invoke for each item
60 | */
61 | export function forEach (obj, fn) {
62 | // Don't bother if no value provided
63 | if (obj === null || typeof obj === 'undefined') {
64 | return
65 | }
66 |
67 | // Force an array if not already something iterable
68 | if (typeof obj !== 'object') {
69 | /*eslint no-param-reassign:0*/
70 | obj = [obj]
71 | }
72 |
73 | if (isArray(obj)) {
74 | // Iterate over array values
75 | for (var i = 0, l = obj.length; i < l; i++) {
76 | fn.call(null, obj[i], i, obj)
77 | }
78 | } else {
79 | // Iterate over object keys
80 | for (var key in obj) {
81 | if (Object.prototype.hasOwnProperty.call(obj, key)) {
82 | fn.call(null, obj[key], key, obj)
83 | }
84 | }
85 | }
86 | }
87 |
88 | /**
89 | * 是否为boolean 值
90 | * @param val
91 | * @returns {boolean}
92 | */
93 | export function isBoolean(val) {
94 | return typeof val === 'boolean'
95 | }
96 |
97 | /**
98 | * 是否为真正的对象{} new Object
99 | * @param {any} obj - 检测的对象
100 | * @returns {boolean}
101 | */
102 | export function isPlainObject(obj) {
103 | return Object.prototype.toString.call(obj) === '[object Object]'
104 | }
105 |
106 |
107 |
108 | /**
109 | * Function equal to merge with the difference being that no reference
110 | * to original objects is kept.
111 | *
112 | * @see merge
113 | * @param {Object} obj1 Object to merge
114 | * @returns {Object} Result of all merge properties
115 | */
116 | export function deepMerge(/* obj1, obj2, obj3, ... */) {
117 | let result = {}
118 | function assignValue(val, key) {
119 | if (typeof result[key] === 'object' && typeof val === 'object') {
120 | result[key] = deepMerge(result[key], val)
121 | } else if (typeof val === 'object') {
122 | result[key] = deepMerge({}, val)
123 | } else {
124 | result[key] = val
125 | }
126 | }
127 | for (let i = 0, l = arguments.length; i < l; i++) {
128 | forEach(arguments[i], assignValue)
129 | }
130 | return result
131 | }
132 |
133 | export function isUndefined (val) {
134 | return typeof val === 'undefined'
135 | }
136 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | // utils is a library of generic helper functions non-specific to axios
4 |
5 | var toString = Object.prototype.toString
6 |
7 | /**
8 | * Determine if a value is an Array
9 | *
10 | * @param {Object} val The value to test
11 | * @returns {boolean} True if value is an Array, otherwise false
12 | */
13 | export function isArray (val) {
14 | return toString.call(val) === '[object Array]'
15 | }
16 |
17 |
18 | /**
19 | * Determine if a value is an Object
20 | *
21 | * @param {Object} val The value to test
22 | * @returns {boolean} True if value is an Object, otherwise false
23 | */
24 | export function isObject (val) {
25 | return val !== null && typeof val === 'object'
26 | }
27 |
28 | /**
29 | * Determine if a value is a Date
30 | *
31 | * @param {Object} val The value to test
32 | * @returns {boolean} True if value is a Date, otherwise false
33 | */
34 | export function isDate (val) {
35 | return toString.call(val) === '[object Date]'
36 | }
37 |
38 | /**
39 | * Determine if a value is a URLSearchParams object
40 | *
41 | * @param {Object} val The value to test
42 | * @returns {boolean} True if value is a URLSearchParams object, otherwise false
43 | */
44 | export function isURLSearchParams (val) {
45 | return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
46 | }
47 |
48 |
49 | /**
50 | * Iterate over an Array or an Object invoking a function for each item.
51 | *
52 | * If `obj` is an Array callback will be called passing
53 | * the value, index, and complete array for each item.
54 | *
55 | * If 'obj' is an Object callback will be called passing
56 | * the value, key, and complete object for each property.
57 | *
58 | * @param {Object|Array} obj The object to iterate
59 | * @param {Function} fn The callback to invoke for each item
60 | */
61 | export function forEach (obj, fn) {
62 | // Don't bother if no value provided
63 | if (obj === null || typeof obj === 'undefined') {
64 | return
65 | }
66 |
67 | // Force an array if not already something iterable
68 | if (typeof obj !== 'object') {
69 | /*eslint no-param-reassign:0*/
70 | obj = [obj]
71 | }
72 |
73 | if (isArray(obj)) {
74 | // Iterate over array values
75 | for (var i = 0, l = obj.length; i < l; i++) {
76 | fn.call(null, obj[i], i, obj)
77 | }
78 | } else {
79 | // Iterate over object keys
80 | for (var key in obj) {
81 | if (Object.prototype.hasOwnProperty.call(obj, key)) {
82 | fn.call(null, obj[key], key, obj)
83 | }
84 | }
85 | }
86 | }
87 |
88 | /**
89 | * 是否为boolean 值
90 | * @param val
91 | * @returns {boolean}
92 | */
93 | export function isBoolean(val) {
94 | return typeof val === 'boolean'
95 | }
96 |
97 | /**
98 | * 是否为真正的对象{} new Object
99 | * @param {any} obj - 检测的对象
100 | * @returns {boolean}
101 | */
102 | export function isPlainObject(obj) {
103 | return Object.prototype.toString.call(obj) === '[object Object]'
104 | }
105 |
106 |
107 |
108 | /**
109 | * Function equal to merge with the difference being that no reference
110 | * to original objects is kept.
111 | *
112 | * @see merge
113 | * @param {Object} obj1 Object to merge
114 | * @returns {Object} Result of all merge properties
115 | */
116 | export function deepMerge(/* obj1, obj2, obj3, ... */) {
117 | let result = {}
118 | function assignValue(val, key) {
119 | if (typeof result[key] === 'object' && typeof val === 'object') {
120 | result[key] = deepMerge(result[key], val)
121 | } else if (typeof val === 'object') {
122 | result[key] = deepMerge({}, val)
123 | } else {
124 | result[key] = val
125 | }
126 | }
127 | for (let i = 0, l = arguments.length; i < l; i++) {
128 | forEach(arguments[i], assignValue)
129 | }
130 | return result
131 | }
132 |
133 | export function isUndefined (val) {
134 | return typeof val === 'undefined'
135 | }
136 |
--------------------------------------------------------------------------------
/src/lib/core/mergeConfig.js:
--------------------------------------------------------------------------------
1 | import {deepMerge, isUndefined} from '../utils'
2 |
3 | /**
4 | * 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
5 | * @param {Array} keys - 配置项
6 | * @param {Object} globalsConfig - 当前的全局配置
7 | * @param {Object} config2 - 局部配置
8 | * @return {{}}
9 | */
10 | const mergeKeys = (keys, globalsConfig, config2) => {
11 | let config = {}
12 | keys.forEach(prop => {
13 | if (!isUndefined(config2[prop])) {
14 | config[prop] = config2[prop]
15 | } else if (!isUndefined(globalsConfig[prop])) {
16 | config[prop] = globalsConfig[prop]
17 | }
18 | })
19 | return config
20 | }
21 | /**
22 | *
23 | * @param globalsConfig - 当前实例的全局配置
24 | * @param config2 - 当前的局部配置
25 | * @return - 合并后的配置
26 | */
27 | export default (globalsConfig, config2 = {}) => {
28 | const method = config2.method || globalsConfig.method || 'GET'
29 | let config = {
30 | baseURL: config2.baseURL || globalsConfig.baseURL || '',
31 | method: method,
32 | url: config2.url || '',
33 | params: config2.params || {},
34 | custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})},
35 | header: deepMerge(globalsConfig.header || {}, config2.header || {})
36 | }
37 | const defaultToConfig2Keys = ['getTask', 'validateStatus', 'paramsSerializer', 'forcedJSONParsing']
38 | config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)}
39 |
40 | // eslint-disable-next-line no-empty
41 | if (method === 'DOWNLOAD') {
42 | const downloadKeys = [
43 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
44 | 'timeout',
45 | // #endif
46 | // #ifdef MP
47 | 'filePath',
48 | // #endif
49 | ]
50 | config = {...config, ...mergeKeys(downloadKeys, globalsConfig, config2)}
51 | } else if (method === 'UPLOAD') {
52 | delete config.header['content-type']
53 | delete config.header['Content-Type']
54 | const uploadKeys = [
55 | // #ifdef APP-PLUS || H5
56 | 'files',
57 | // #endif
58 | // #ifdef MP-ALIPAY
59 | 'fileType',
60 | // #endif
61 | // #ifdef H5
62 | 'file',
63 | // #endif
64 | 'filePath',
65 | 'name',
66 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
67 | 'timeout',
68 | // #endif
69 | 'formData',
70 | ]
71 | uploadKeys.forEach(prop => {
72 | if (!isUndefined(config2[prop])) {
73 | config[prop] = config2[prop]
74 | }
75 | })
76 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
77 | if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
78 | config['timeout'] = globalsConfig['timeout']
79 | }
80 | // #endif
81 | } else {
82 | const defaultsKeys = [
83 | 'data',
84 | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
85 | 'timeout',
86 | // #endif
87 | 'dataType',
88 | // #ifndef MP-ALIPAY
89 | 'responseType',
90 | // #endif
91 | // #ifdef APP-PLUS
92 | 'sslVerify',
93 | // #endif
94 | // #ifdef H5
95 | 'withCredentials',
96 | // #endif
97 | // #ifdef APP-PLUS
98 | 'firstIpv4',
99 | // #endif
100 | // #ifdef MP-WEIXIN
101 | 'enableHttp2',
102 | 'enableQuic',
103 | // #endif
104 | // #ifdef MP-TOUTIAO || MP-WEIXIN
105 | 'enableCache',
106 | // #endif
107 | // #ifdef MP-WEIXIN
108 | 'enableHttpDNS',
109 | 'httpDNSServiceId',
110 | 'enableChunked',
111 | 'forceCellularNetwork',
112 | // #endif
113 | // #ifdef MP-ALIPAY
114 | 'enableCookie',
115 | // #endif
116 | // #ifdef MP-BAIDU
117 | 'cloudCache',
118 | 'defer'
119 | // #endif
120 |
121 | ]
122 | config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)}
123 | }
124 |
125 | return config
126 | }
127 |
--------------------------------------------------------------------------------
/DCloud/luch-request/core/mergeConfig.js:
--------------------------------------------------------------------------------
1 | import {deepMerge, isUndefined} from '../utils'
2 |
3 | /**
4 | * 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
5 | * @param {Array} keys - 配置项
6 | * @param {Object} globalsConfig - 当前的全局配置
7 | * @param {Object} config2 - 局部配置
8 | * @return {{}}
9 | */
10 | const mergeKeys = (keys, globalsConfig, config2) => {
11 | let config = {}
12 | keys.forEach(prop => {
13 | if (!isUndefined(config2[prop])) {
14 | config[prop] = config2[prop]
15 | } else if (!isUndefined(globalsConfig[prop])) {
16 | config[prop] = globalsConfig[prop]
17 | }
18 | })
19 | return config
20 | }
21 | /**
22 | *
23 | * @param globalsConfig - 当前实例的全局配置
24 | * @param config2 - 当前的局部配置
25 | * @return - 合并后的配置
26 | */
27 | export default (globalsConfig, config2 = {}) => {
28 | const method = config2.method || globalsConfig.method || 'GET'
29 | let config = {
30 | baseURL: config2.baseURL || globalsConfig.baseURL || '',
31 | method: method,
32 | url: config2.url || '',
33 | params: config2.params || {},
34 | custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})},
35 | header: deepMerge(globalsConfig.header || {}, config2.header || {})
36 | }
37 | const defaultToConfig2Keys = ['getTask', 'validateStatus', 'paramsSerializer', 'forcedJSONParsing']
38 | config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)}
39 |
40 | // eslint-disable-next-line no-empty
41 | if (method === 'DOWNLOAD') {
42 | const downloadKeys = [
43 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
44 | 'timeout',
45 | // #endif
46 | // #ifdef MP
47 | 'filePath',
48 | // #endif
49 | ]
50 | config = {...config, ...mergeKeys(downloadKeys, globalsConfig, config2)}
51 | } else if (method === 'UPLOAD') {
52 | delete config.header['content-type']
53 | delete config.header['Content-Type']
54 | const uploadKeys = [
55 | // #ifdef APP-PLUS || H5
56 | 'files',
57 | // #endif
58 | // #ifdef MP-ALIPAY
59 | 'fileType',
60 | // #endif
61 | // #ifdef H5
62 | 'file',
63 | // #endif
64 | 'filePath',
65 | 'name',
66 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
67 | 'timeout',
68 | // #endif
69 | 'formData',
70 | ]
71 | uploadKeys.forEach(prop => {
72 | if (!isUndefined(config2[prop])) {
73 | config[prop] = config2[prop]
74 | }
75 | })
76 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
77 | if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
78 | config['timeout'] = globalsConfig['timeout']
79 | }
80 | // #endif
81 | } else {
82 | const defaultsKeys = [
83 | 'data',
84 | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
85 | 'timeout',
86 | // #endif
87 | 'dataType',
88 | // #ifndef MP-ALIPAY
89 | 'responseType',
90 | // #endif
91 | // #ifdef APP-PLUS
92 | 'sslVerify',
93 | // #endif
94 | // #ifdef H5
95 | 'withCredentials',
96 | // #endif
97 | // #ifdef APP-PLUS
98 | 'firstIpv4',
99 | // #endif
100 | // #ifdef MP-WEIXIN
101 | 'enableHttp2',
102 | 'enableQuic',
103 | // #endif
104 | // #ifdef MP-TOUTIAO || MP-WEIXIN
105 | 'enableCache',
106 | // #endif
107 | // #ifdef MP-WEIXIN
108 | 'enableHttpDNS',
109 | 'httpDNSServiceId',
110 | 'enableChunked',
111 | 'forceCellularNetwork',
112 | // #endif
113 | // #ifdef MP-ALIPAY
114 | 'enableCookie',
115 | // #endif
116 | // #ifdef MP-BAIDU
117 | 'cloudCache',
118 | 'defer'
119 | // #endif
120 |
121 | ]
122 | config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)}
123 | }
124 |
125 | return config
126 | }
127 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/core/mergeConfig.js:
--------------------------------------------------------------------------------
1 | import {deepMerge, isUndefined} from '../utils'
2 |
3 | /**
4 | * 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
5 | * @param {Array} keys - 配置项
6 | * @param {Object} globalsConfig - 当前的全局配置
7 | * @param {Object} config2 - 局部配置
8 | * @return {{}}
9 | */
10 | const mergeKeys = (keys, globalsConfig, config2) => {
11 | let config = {}
12 | keys.forEach(prop => {
13 | if (!isUndefined(config2[prop])) {
14 | config[prop] = config2[prop]
15 | } else if (!isUndefined(globalsConfig[prop])) {
16 | config[prop] = globalsConfig[prop]
17 | }
18 | })
19 | return config
20 | }
21 | /**
22 | *
23 | * @param globalsConfig - 当前实例的全局配置
24 | * @param config2 - 当前的局部配置
25 | * @return - 合并后的配置
26 | */
27 | export default (globalsConfig, config2 = {}) => {
28 | const method = config2.method || globalsConfig.method || 'GET'
29 | let config = {
30 | baseURL: config2.baseURL || globalsConfig.baseURL || '',
31 | method: method,
32 | url: config2.url || '',
33 | params: config2.params || {},
34 | custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})},
35 | header: deepMerge(globalsConfig.header || {}, config2.header || {})
36 | }
37 | const defaultToConfig2Keys = ['getTask', 'validateStatus', 'paramsSerializer', 'forcedJSONParsing']
38 | config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)}
39 |
40 | // eslint-disable-next-line no-empty
41 | if (method === 'DOWNLOAD') {
42 | const downloadKeys = [
43 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
44 | 'timeout',
45 | // #endif
46 | // #ifdef MP
47 | 'filePath',
48 | // #endif
49 | ]
50 | config = {...config, ...mergeKeys(downloadKeys, globalsConfig, config2)}
51 | } else if (method === 'UPLOAD') {
52 | delete config.header['content-type']
53 | delete config.header['Content-Type']
54 | const uploadKeys = [
55 | // #ifdef APP-PLUS || H5
56 | 'files',
57 | // #endif
58 | // #ifdef MP-ALIPAY
59 | 'fileType',
60 | // #endif
61 | // #ifdef H5
62 | 'file',
63 | // #endif
64 | 'filePath',
65 | 'name',
66 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
67 | 'timeout',
68 | // #endif
69 | 'formData',
70 | ]
71 | uploadKeys.forEach(prop => {
72 | if (!isUndefined(config2[prop])) {
73 | config[prop] = config2[prop]
74 | }
75 | })
76 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
77 | if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
78 | config['timeout'] = globalsConfig['timeout']
79 | }
80 | // #endif
81 | } else {
82 | const defaultsKeys = [
83 | 'data',
84 | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
85 | 'timeout',
86 | // #endif
87 | 'dataType',
88 | // #ifndef MP-ALIPAY
89 | 'responseType',
90 | // #endif
91 | // #ifdef APP-PLUS
92 | 'sslVerify',
93 | // #endif
94 | // #ifdef H5
95 | 'withCredentials',
96 | // #endif
97 | // #ifdef APP-PLUS
98 | 'firstIpv4',
99 | // #endif
100 | // #ifdef MP-WEIXIN
101 | 'enableHttp2',
102 | 'enableQuic',
103 | // #endif
104 | // #ifdef MP-TOUTIAO || MP-WEIXIN
105 | 'enableCache',
106 | // #endif
107 | // #ifdef MP-WEIXIN
108 | 'enableHttpDNS',
109 | 'httpDNSServiceId',
110 | 'enableChunked',
111 | 'forceCellularNetwork',
112 | // #endif
113 | // #ifdef MP-ALIPAY
114 | 'enableCookie',
115 | // #endif
116 | // #ifdef MP-BAIDU
117 | 'cloudCache',
118 | 'defer'
119 | // #endif
120 |
121 | ]
122 | config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)}
123 | }
124 |
125 | return config
126 | }
127 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/core/mergeConfig.js:
--------------------------------------------------------------------------------
1 | import {deepMerge, isUndefined} from '../utils'
2 |
3 | /**
4 | * 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
5 | * @param {Array} keys - 配置项
6 | * @param {Object} globalsConfig - 当前的全局配置
7 | * @param {Object} config2 - 局部配置
8 | * @return {{}}
9 | */
10 | const mergeKeys = (keys, globalsConfig, config2) => {
11 | let config = {}
12 | keys.forEach(prop => {
13 | if (!isUndefined(config2[prop])) {
14 | config[prop] = config2[prop]
15 | } else if (!isUndefined(globalsConfig[prop])) {
16 | config[prop] = globalsConfig[prop]
17 | }
18 | })
19 | return config
20 | }
21 | /**
22 | *
23 | * @param globalsConfig - 当前实例的全局配置
24 | * @param config2 - 当前的局部配置
25 | * @return - 合并后的配置
26 | */
27 | export default (globalsConfig, config2 = {}) => {
28 | const method = config2.method || globalsConfig.method || 'GET'
29 | let config = {
30 | baseURL: config2.baseURL || globalsConfig.baseURL || '',
31 | method: method,
32 | url: config2.url || '',
33 | params: config2.params || {},
34 | custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})},
35 | header: deepMerge(globalsConfig.header || {}, config2.header || {})
36 | }
37 | const defaultToConfig2Keys = ['getTask', 'validateStatus', 'paramsSerializer', 'forcedJSONParsing']
38 | config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)}
39 |
40 | // eslint-disable-next-line no-empty
41 | if (method === 'DOWNLOAD') {
42 | const downloadKeys = [
43 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
44 | 'timeout',
45 | // #endif
46 | // #ifdef MP
47 | 'filePath',
48 | // #endif
49 | ]
50 | config = {...config, ...mergeKeys(downloadKeys, globalsConfig, config2)}
51 | } else if (method === 'UPLOAD') {
52 | delete config.header['content-type']
53 | delete config.header['Content-Type']
54 | const uploadKeys = [
55 | // #ifdef APP-PLUS || H5
56 | 'files',
57 | // #endif
58 | // #ifdef MP-ALIPAY
59 | 'fileType',
60 | // #endif
61 | // #ifdef H5
62 | 'file',
63 | // #endif
64 | 'filePath',
65 | 'name',
66 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
67 | 'timeout',
68 | // #endif
69 | 'formData',
70 | ]
71 | uploadKeys.forEach(prop => {
72 | if (!isUndefined(config2[prop])) {
73 | config[prop] = config2[prop]
74 | }
75 | })
76 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
77 | if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
78 | config['timeout'] = globalsConfig['timeout']
79 | }
80 | // #endif
81 | } else {
82 | const defaultsKeys = [
83 | 'data',
84 | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
85 | 'timeout',
86 | // #endif
87 | 'dataType',
88 | // #ifndef MP-ALIPAY
89 | 'responseType',
90 | // #endif
91 | // #ifdef APP-PLUS
92 | 'sslVerify',
93 | // #endif
94 | // #ifdef H5
95 | 'withCredentials',
96 | // #endif
97 | // #ifdef APP-PLUS
98 | 'firstIpv4',
99 | // #endif
100 | // #ifdef MP-WEIXIN
101 | 'enableHttp2',
102 | 'enableQuic',
103 | // #endif
104 | // #ifdef MP-TOUTIAO || MP-WEIXIN
105 | 'enableCache',
106 | // #endif
107 | // #ifdef MP-WEIXIN
108 | 'enableHttpDNS',
109 | 'httpDNSServiceId',
110 | 'enableChunked',
111 | 'forceCellularNetwork',
112 | // #endif
113 | // #ifdef MP-ALIPAY
114 | 'enableCookie',
115 | // #endif
116 | // #ifdef MP-BAIDU
117 | 'cloudCache',
118 | 'defer'
119 | // #endif
120 |
121 | ]
122 | config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)}
123 | }
124 |
125 | return config
126 | }
127 |
--------------------------------------------------------------------------------
/test/dev-test/pages/index/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | luch-request:
9 | luch-request官网
10 |
11 |
12 | 我的博客:
13 | luch的博客
14 |
15 |
16 |
17 |
18 |
19 |
127 |
128 |
154 |
--------------------------------------------------------------------------------
/example/request-demo/pages/index/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | luch-request:
10 | luch-request官网
11 |
12 |
13 | 我的博客:
14 | luch的博客
15 |
16 |
17 |
18 |
19 |
20 |
131 |
132 |
158 |
--------------------------------------------------------------------------------
/src/lib/adapters/index.js:
--------------------------------------------------------------------------------
1 | import buildURL from '../helpers/buildURL'
2 | import buildFullPath from '../core/buildFullPath'
3 | import settle from '../core/settle'
4 | import {isUndefined} from "../utils"
5 |
6 | /**
7 | * 返回可选值存在的配置
8 | * @param {Array} keys - 可选值数组
9 | * @param {Object} config2 - 配置
10 | * @return {{}} - 存在的配置项
11 | */
12 | const mergeKeys = (keys, config2) => {
13 | let config = {}
14 | keys.forEach(prop => {
15 | if (!isUndefined(config2[prop])) {
16 | config[prop] = config2[prop]
17 | }
18 | })
19 | return config
20 | }
21 | export default (config) => {
22 | return new Promise((resolve, reject) => {
23 | let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer)
24 | const _config = {
25 | url: fullPath,
26 | header: config.header,
27 | complete: (response) => {
28 | config.fullPath = fullPath
29 | response.config = config
30 | response.rawData = response.data
31 | try {
32 | let jsonParseHandle = false
33 | const forcedJSONParsingType = typeof config.forcedJSONParsing
34 | if (forcedJSONParsingType === 'boolean') {
35 | jsonParseHandle = config.forcedJSONParsing
36 | } else if (forcedJSONParsingType === 'object') {
37 | const includesMethod = config.forcedJSONParsing.include || []
38 | jsonParseHandle = includesMethod.includes(config.method)
39 | }
40 |
41 | // 对可能字符串不是json 的情况容错
42 | if (jsonParseHandle && typeof response.data === 'string') {
43 | response.data = JSON.parse(response.data)
44 | }
45 | // eslint-disable-next-line no-empty
46 | } catch (e) {
47 | }
48 | settle(resolve, reject, response)
49 | }
50 | }
51 | let requestTask
52 | if (config.method === 'UPLOAD') {
53 | delete _config.header['content-type']
54 | delete _config.header['Content-Type']
55 | let otherConfig = {
56 | // #ifdef MP-ALIPAY
57 | fileType: config.fileType,
58 | // #endif
59 | filePath: config.filePath,
60 | name: config.name
61 | }
62 | const optionalKeys = [
63 | // #ifdef APP-PLUS || H5
64 | 'files',
65 | // #endif
66 | // #ifdef H5
67 | 'file',
68 | // #endif
69 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
70 | 'timeout',
71 | // #endif
72 | 'formData'
73 | ]
74 | requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)})
75 | } else if (config.method === 'DOWNLOAD') {
76 | const optionalKeys = [
77 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
78 | 'timeout',
79 | // #endif
80 | // #ifdef MP
81 | 'filePath',
82 | // #endif
83 | ]
84 | requestTask = uni.downloadFile({..._config, ...mergeKeys(optionalKeys, config)})
85 | } else {
86 | const optionalKeys = [
87 | 'data',
88 | 'method',
89 | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
90 | 'timeout',
91 | // #endif
92 | 'dataType',
93 | // #ifndef MP-ALIPAY
94 | 'responseType',
95 | // #endif
96 | // #ifdef APP-PLUS
97 | 'sslVerify',
98 | // #endif
99 | // #ifdef H5
100 | 'withCredentials',
101 | // #endif
102 | // #ifdef APP-PLUS
103 | 'firstIpv4',
104 | // #endif
105 | // #ifdef MP-WEIXIN
106 | 'enableHttp2',
107 | 'enableQuic',
108 | // #endif
109 | // #ifdef MP-TOUTIAO || MP-WEIXIN
110 | 'enableCache',
111 | // #endif
112 | // #ifdef MP-WEIXIN
113 | 'enableHttpDNS',
114 | 'httpDNSServiceId',
115 | 'enableChunked',
116 | 'forceCellularNetwork',
117 | // #endif
118 | // #ifdef MP-ALIPAY
119 | 'enableCookie',
120 | // #endif
121 | // #ifdef MP-BAIDU
122 | 'cloudCache',
123 | 'defer'
124 | // #endif
125 | ]
126 | requestTask = uni.request({..._config, ...mergeKeys(optionalKeys, config)})
127 | }
128 | if (config.getTask) {
129 | config.getTask(requestTask, config)
130 | }
131 | })
132 | }
133 |
--------------------------------------------------------------------------------
/DCloud/luch-request/adapters/index.js:
--------------------------------------------------------------------------------
1 | import buildURL from '../helpers/buildURL'
2 | import buildFullPath from '../core/buildFullPath'
3 | import settle from '../core/settle'
4 | import {isUndefined} from "../utils"
5 |
6 | /**
7 | * 返回可选值存在的配置
8 | * @param {Array} keys - 可选值数组
9 | * @param {Object} config2 - 配置
10 | * @return {{}} - 存在的配置项
11 | */
12 | const mergeKeys = (keys, config2) => {
13 | let config = {}
14 | keys.forEach(prop => {
15 | if (!isUndefined(config2[prop])) {
16 | config[prop] = config2[prop]
17 | }
18 | })
19 | return config
20 | }
21 | export default (config) => {
22 | return new Promise((resolve, reject) => {
23 | let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer)
24 | const _config = {
25 | url: fullPath,
26 | header: config.header,
27 | complete: (response) => {
28 | config.fullPath = fullPath
29 | response.config = config
30 | response.rawData = response.data
31 | try {
32 | let jsonParseHandle = false
33 | const forcedJSONParsingType = typeof config.forcedJSONParsing
34 | if (forcedJSONParsingType === 'boolean') {
35 | jsonParseHandle = config.forcedJSONParsing
36 | } else if (forcedJSONParsingType === 'object') {
37 | const includesMethod = config.forcedJSONParsing.include || []
38 | jsonParseHandle = includesMethod.includes(config.method)
39 | }
40 |
41 | // 对可能字符串不是json 的情况容错
42 | if (jsonParseHandle && typeof response.data === 'string') {
43 | response.data = JSON.parse(response.data)
44 | }
45 | // eslint-disable-next-line no-empty
46 | } catch (e) {
47 | }
48 | settle(resolve, reject, response)
49 | }
50 | }
51 | let requestTask
52 | if (config.method === 'UPLOAD') {
53 | delete _config.header['content-type']
54 | delete _config.header['Content-Type']
55 | let otherConfig = {
56 | // #ifdef MP-ALIPAY
57 | fileType: config.fileType,
58 | // #endif
59 | filePath: config.filePath,
60 | name: config.name
61 | }
62 | const optionalKeys = [
63 | // #ifdef APP-PLUS || H5
64 | 'files',
65 | // #endif
66 | // #ifdef H5
67 | 'file',
68 | // #endif
69 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
70 | 'timeout',
71 | // #endif
72 | 'formData'
73 | ]
74 | requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)})
75 | } else if (config.method === 'DOWNLOAD') {
76 | const optionalKeys = [
77 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
78 | 'timeout',
79 | // #endif
80 | // #ifdef MP
81 | 'filePath',
82 | // #endif
83 | ]
84 | requestTask = uni.downloadFile({..._config, ...mergeKeys(optionalKeys, config)})
85 | } else {
86 | const optionalKeys = [
87 | 'data',
88 | 'method',
89 | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
90 | 'timeout',
91 | // #endif
92 | 'dataType',
93 | // #ifndef MP-ALIPAY
94 | 'responseType',
95 | // #endif
96 | // #ifdef APP-PLUS
97 | 'sslVerify',
98 | // #endif
99 | // #ifdef H5
100 | 'withCredentials',
101 | // #endif
102 | // #ifdef APP-PLUS
103 | 'firstIpv4',
104 | // #endif
105 | // #ifdef MP-WEIXIN
106 | 'enableHttp2',
107 | 'enableQuic',
108 | // #endif
109 | // #ifdef MP-TOUTIAO || MP-WEIXIN
110 | 'enableCache',
111 | // #endif
112 | // #ifdef MP-WEIXIN
113 | 'enableHttpDNS',
114 | 'httpDNSServiceId',
115 | 'enableChunked',
116 | 'forceCellularNetwork',
117 | // #endif
118 | // #ifdef MP-ALIPAY
119 | 'enableCookie',
120 | // #endif
121 | // #ifdef MP-BAIDU
122 | 'cloudCache',
123 | 'defer'
124 | // #endif
125 | ]
126 | requestTask = uni.request({..._config, ...mergeKeys(optionalKeys, config)})
127 | }
128 | if (config.getTask) {
129 | config.getTask(requestTask, config)
130 | }
131 | })
132 | }
133 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/adapters/index.js:
--------------------------------------------------------------------------------
1 | import buildURL from '../helpers/buildURL'
2 | import buildFullPath from '../core/buildFullPath'
3 | import settle from '../core/settle'
4 | import {isUndefined} from "../utils"
5 |
6 | /**
7 | * 返回可选值存在的配置
8 | * @param {Array} keys - 可选值数组
9 | * @param {Object} config2 - 配置
10 | * @return {{}} - 存在的配置项
11 | */
12 | const mergeKeys = (keys, config2) => {
13 | let config = {}
14 | keys.forEach(prop => {
15 | if (!isUndefined(config2[prop])) {
16 | config[prop] = config2[prop]
17 | }
18 | })
19 | return config
20 | }
21 | export default (config) => {
22 | return new Promise((resolve, reject) => {
23 | let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer)
24 | const _config = {
25 | url: fullPath,
26 | header: config.header,
27 | complete: (response) => {
28 | config.fullPath = fullPath
29 | response.config = config
30 | response.rawData = response.data
31 | try {
32 | let jsonParseHandle = false
33 | const forcedJSONParsingType = typeof config.forcedJSONParsing
34 | if (forcedJSONParsingType === 'boolean') {
35 | jsonParseHandle = config.forcedJSONParsing
36 | } else if (forcedJSONParsingType === 'object') {
37 | const includesMethod = config.forcedJSONParsing.include || []
38 | jsonParseHandle = includesMethod.includes(config.method)
39 | }
40 |
41 | // 对可能字符串不是json 的情况容错
42 | if (jsonParseHandle && typeof response.data === 'string') {
43 | response.data = JSON.parse(response.data)
44 | }
45 | // eslint-disable-next-line no-empty
46 | } catch (e) {
47 | }
48 | settle(resolve, reject, response)
49 | }
50 | }
51 | let requestTask
52 | if (config.method === 'UPLOAD') {
53 | delete _config.header['content-type']
54 | delete _config.header['Content-Type']
55 | let otherConfig = {
56 | // #ifdef MP-ALIPAY
57 | fileType: config.fileType,
58 | // #endif
59 | filePath: config.filePath,
60 | name: config.name
61 | }
62 | const optionalKeys = [
63 | // #ifdef APP-PLUS || H5
64 | 'files',
65 | // #endif
66 | // #ifdef H5
67 | 'file',
68 | // #endif
69 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
70 | 'timeout',
71 | // #endif
72 | 'formData'
73 | ]
74 | requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)})
75 | } else if (config.method === 'DOWNLOAD') {
76 | const optionalKeys = [
77 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
78 | 'timeout',
79 | // #endif
80 | // #ifdef MP
81 | 'filePath',
82 | // #endif
83 | ]
84 | requestTask = uni.downloadFile({..._config, ...mergeKeys(optionalKeys, config)})
85 | } else {
86 | const optionalKeys = [
87 | 'data',
88 | 'method',
89 | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
90 | 'timeout',
91 | // #endif
92 | 'dataType',
93 | // #ifndef MP-ALIPAY
94 | 'responseType',
95 | // #endif
96 | // #ifdef APP-PLUS
97 | 'sslVerify',
98 | // #endif
99 | // #ifdef H5
100 | 'withCredentials',
101 | // #endif
102 | // #ifdef APP-PLUS
103 | 'firstIpv4',
104 | // #endif
105 | // #ifdef MP-WEIXIN
106 | 'enableHttp2',
107 | 'enableQuic',
108 | // #endif
109 | // #ifdef MP-TOUTIAO || MP-WEIXIN
110 | 'enableCache',
111 | // #endif
112 | // #ifdef MP-WEIXIN
113 | 'enableHttpDNS',
114 | 'httpDNSServiceId',
115 | 'enableChunked',
116 | 'forceCellularNetwork',
117 | // #endif
118 | // #ifdef MP-ALIPAY
119 | 'enableCookie',
120 | // #endif
121 | // #ifdef MP-BAIDU
122 | 'cloudCache',
123 | 'defer'
124 | // #endif
125 | ]
126 | requestTask = uni.request({..._config, ...mergeKeys(optionalKeys, config)})
127 | }
128 | if (config.getTask) {
129 | config.getTask(requestTask, config)
130 | }
131 | })
132 | }
133 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/adapters/index.js:
--------------------------------------------------------------------------------
1 | import buildURL from '../helpers/buildURL'
2 | import buildFullPath from '../core/buildFullPath'
3 | import settle from '../core/settle'
4 | import {isUndefined} from "../utils"
5 |
6 | /**
7 | * 返回可选值存在的配置
8 | * @param {Array} keys - 可选值数组
9 | * @param {Object} config2 - 配置
10 | * @return {{}} - 存在的配置项
11 | */
12 | const mergeKeys = (keys, config2) => {
13 | let config = {}
14 | keys.forEach(prop => {
15 | if (!isUndefined(config2[prop])) {
16 | config[prop] = config2[prop]
17 | }
18 | })
19 | return config
20 | }
21 | export default (config) => {
22 | return new Promise((resolve, reject) => {
23 | let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer)
24 | const _config = {
25 | url: fullPath,
26 | header: config.header,
27 | complete: (response) => {
28 | config.fullPath = fullPath
29 | response.config = config
30 | response.rawData = response.data
31 | try {
32 | let jsonParseHandle = false
33 | const forcedJSONParsingType = typeof config.forcedJSONParsing
34 | if (forcedJSONParsingType === 'boolean') {
35 | jsonParseHandle = config.forcedJSONParsing
36 | } else if (forcedJSONParsingType === 'object') {
37 | const includesMethod = config.forcedJSONParsing.include || []
38 | jsonParseHandle = includesMethod.includes(config.method)
39 | }
40 |
41 | // 对可能字符串不是json 的情况容错
42 | if (jsonParseHandle && typeof response.data === 'string') {
43 | response.data = JSON.parse(response.data)
44 | }
45 | // eslint-disable-next-line no-empty
46 | } catch (e) {
47 | }
48 | settle(resolve, reject, response)
49 | }
50 | }
51 | let requestTask
52 | if (config.method === 'UPLOAD') {
53 | delete _config.header['content-type']
54 | delete _config.header['Content-Type']
55 | let otherConfig = {
56 | // #ifdef MP-ALIPAY
57 | fileType: config.fileType,
58 | // #endif
59 | filePath: config.filePath,
60 | name: config.name
61 | }
62 | const optionalKeys = [
63 | // #ifdef APP-PLUS || H5
64 | 'files',
65 | // #endif
66 | // #ifdef H5
67 | 'file',
68 | // #endif
69 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
70 | 'timeout',
71 | // #endif
72 | 'formData'
73 | ]
74 | requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)})
75 | } else if (config.method === 'DOWNLOAD') {
76 | const optionalKeys = [
77 | // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
78 | 'timeout',
79 | // #endif
80 | // #ifdef MP
81 | 'filePath',
82 | // #endif
83 | ]
84 | requestTask = uni.downloadFile({..._config, ...mergeKeys(optionalKeys, config)})
85 | } else {
86 | const optionalKeys = [
87 | 'data',
88 | 'method',
89 | // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
90 | 'timeout',
91 | // #endif
92 | 'dataType',
93 | // #ifndef MP-ALIPAY
94 | 'responseType',
95 | // #endif
96 | // #ifdef APP-PLUS
97 | 'sslVerify',
98 | // #endif
99 | // #ifdef H5
100 | 'withCredentials',
101 | // #endif
102 | // #ifdef APP-PLUS
103 | 'firstIpv4',
104 | // #endif
105 | // #ifdef MP-WEIXIN
106 | 'enableHttp2',
107 | 'enableQuic',
108 | // #endif
109 | // #ifdef MP-TOUTIAO || MP-WEIXIN
110 | 'enableCache',
111 | // #endif
112 | // #ifdef MP-WEIXIN
113 | 'enableHttpDNS',
114 | 'httpDNSServiceId',
115 | 'enableChunked',
116 | 'forceCellularNetwork',
117 | // #endif
118 | // #ifdef MP-ALIPAY
119 | 'enableCookie',
120 | // #endif
121 | // #ifdef MP-BAIDU
122 | 'cloudCache',
123 | 'defer'
124 | // #endif
125 | ]
126 | requestTask = uni.request({..._config, ...mergeKeys(optionalKeys, config)})
127 | }
128 | if (config.getTask) {
129 | config.getTask(requestTask, config)
130 | }
131 | })
132 | }
133 |
--------------------------------------------------------------------------------
/docs/handbook/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar: auto
3 | title: 指南
4 | meta:
5 | - name: description
6 | content: luch-request 是一个基于Promise 开发的uni-app跨平台、项目级别的请求库,它有更小的体积,易用的api,方便简单的自定义能力。luch-request 基于Promise,使用条件编译开发,专用于uni-app项目(事实上,我们可以剔除对应的终端以外的代码,直接在对应终端原生语言使用)。为了降低学习成本,一些api参照axios 设计。并扩展一些其它的api。
7 | ---
8 |
9 |
10 | # 指南
11 |
12 | 介绍
13 | ------------
14 |
15 | luch-request 是一个基于Promise 开发的uni-app跨平台、项目级别的请求库,它有更小的体积,易用的api,方便简单的自定义能力。
16 |
17 | - 支持全局挂载
18 | - 支持多个全局配置实例
19 | - 支持自定义验证器
20 | - 支持文件上传/下载
21 | - 支持task 操作
22 | - 支持自定义参数
23 | - 支持多拦截器
24 | - 对参数的处理比uni.request 更强
25 |
26 | ### 它是如何工作的
27 | luch-request 基于Promise,使用条件编译开发,专用于uni-app项目(事实上,我们可以剔除对应的终端以外的代码,直接在对应终端原生语言使用)。为了降低学习成本,一些api参照axios 设计。并扩展一些其它的api。
28 |
29 | 对于某些终端不支持的option,插件已通过内部实现,过滤不支持的参数。
30 |
31 | 在项目中,我们可以通过`局部引入`和`全局引入`的方式去使用它(参考:[示例项目](https://github.com/lei-mu/luch-request/tree/master/example/request-demo))。
32 |
33 | ### 为什么不是...?
34 |
35 | #### axios
36 | axios 是一个优秀的可用于前端项目和node 的请求库。但是在uni-app 项目中却不能使用它。因为它使用了`xhr` 对象的请求库,但是在除h5终端以外的终端都没有开放xhr对象,所以它无法跨端开发。并且大量的配置在uni-app中不支持,或者没有。无用的代码意味着无用的消耗。它的迭代并不会考虑uni-app。
37 |
38 | #### axios重写`adapter`
39 | 还是那句话,对于uni-app来说它太大太重。大量无用的代码,并不适用于项目。luch-request完全满足项目开发。
40 |
41 | #### 其他的uni request 插件
42 | **非条件编译开发:** 插件市场的部分request没有使用条件编译开发,这对我们项目debug会造成误导影响。并且多余的代码也增大了项目体积。
43 |
44 | **多余的配置项:** 有些插件会把loading、auth等参数加入配置,使其做一些请求之外的操作,这些配置并不是所有人都会使用。**request请求库只需专注于请求即可**。luch-request对额外操作的处理则更为优雅,增加了`custom` 配置,使开发者可以做一些自定义操作。
45 |
46 | **开发构建:** luch-request请求库开发配置了eslint、rollup等等项目级构建打包工具,很大程度上使代码更加标准。
47 |
48 | 其他显而易见的优势就不用说了
49 |
50 | #### uni.request
51 | ...
52 |
53 | 无法满足项目级开发要求,无拦截器,无自定义api.
54 |
55 | 你的使用方式
56 | ```` javascript
57 | uni.request({
58 | url: this.$baseUrl + 'api/user'
59 | method: 'POST',
60 | data: {a:1},
61 | header: {Content-Type: '...', token: '....'}
62 | success: (res) => {},
63 | fail: (err) => {}
64 | })
65 | ````
66 | 使用luch-request后
67 | ```` javascript
68 | this.$http.post('/api/user', {a:1}).then(res => {
69 | ...
70 | }).catch(err => {
71 | ...
72 | })
73 | ````
74 |
75 | luch-request 对特殊参数的处理方式比uni.request 更强。具体可见get,传递数组。
76 |
77 | #### function
78 | 这是我见得大多数人的使用方法。自己写一个function封装。修改配置都是直接改代码。在一些项目中可能出现多个api的情况,无法多实例。
79 |
80 | ...
81 |
82 | 快速上手
83 | ------------
84 |
85 | ### npm
86 |
87 | ```` javascript
88 | npm i luch-request -S
89 | ````
90 | cli 用户使用npm 包需增加以下配置(什么是cli用户)
91 |
92 | 项目根路径下创建`vue.config.js` 文件,增加以下内容
93 | ``` javascript
94 | // vue.config.js
95 | module.exports = {
96 | transpileDependencies: ['luch-request']
97 | }
98 | ```
99 |
100 | ::: warning
101 | cli用户使用npm包,为什么要加以上配置[详见](/issue/#_1-%E4%B8%BA%E4%BB%80%E4%B9%88cli%E7%94%A8%E6%88%B7%E4%B8%8D%E8%83%BD%E4%BD%BF%E7%94%A8-npm-%E6%96%B9%E5%BC%8F%E5%BC%95%E5%85%A5)
102 | :::
103 |
104 | ### github
105 |
106 | GitHub
107 |
108 | 使用DCloud/luch-request 文件夹即可
109 |
110 |
111 | ### DCloud插件市场
112 |
113 | DCloud插件市场
114 |
115 |
116 | tip
117 | ------------
118 | - nvue 不支持全局挂载
119 | - 当前的hbuilderx 版本号:beat-3.0.4 alpha-3.0.4
120 | - 推荐使用下载插件的方式使用。
121 | - license: MIT
122 |
123 |
124 | issue
125 | ------------
126 | - DCloud: 有任何问题或者建议可以=> issue提交,先给个五星好评QAQ!!
127 | - github: Issues
128 |
129 |
130 | 作者想说
131 | ------------
132 | - 写代码很容易,为了让你们看懂写文档真的很lei 0.0
133 | - 最近发现有插件与我雷同,当初接触uni-app 就发现插件市场虽然有封装的不错的request库,但是都没有对多全局配置做处理,都是通过修改源码的方式配置。我首先推出通过class类,并仿照axios的api实现request请求库,并起名‘仿axios封装request网络请求库,支持拦截器全局配置’。他们虽然修改了部分代码,但是功能与性能并没有优化,反而使代码很冗余。希望能推出新的功能,和性能更加强悍的请求库。(2019-05)
134 | - 任何形式的‘参考’、‘借鉴’,请标明作者` luch-request `
135 | ```javascript
136 | luch-request
137 | ```
138 |
139 |
140 | 我有疑惑
141 | ------------
142 | ### 关于问问题
143 | 1. 首先请善于利用搜索引擎,不管百度,还是Google,遇到问题请先自己尝试解决。自己尝试过无法解决,再问。
144 | 2. 不要问类似为什么我的xx无法使用这种问题。请仔细阅读文档,检查代码,或者说明运行环境,把相关代码贴至评论或者发送至我的邮箱,还可以点击DCloud 社区,在里面提问,可能我在里面已经回答了。
145 | 3. 我的代码如果真的出现bug,或者你有好的建议、需求,可以提issue,我看到后会立即解决
146 |
147 |
148 | ### 如何问问题
149 | 1. 问问题之前请换位思考,如果自己要解决这个问题,需要哪些信息
150 | 2. 仔细阅读文档,检查代码
151 | 3. 说明运行环境,比如:app端 ios、android 版本号、手机机型、普遍现象还是个别现象(越详细越好)
152 | 4. 发出代码片段或者截图至邮箱(很重要)`webwork.s@qq.com`
153 | 5. 或者可以在DCloud 社区里发出详细的问题描述
154 | 6. 以上都觉得解决不了你的问题或问题过于复杂难以描述,可以加QQ:`370306150`
155 |
156 |
157 | 其他
158 | ------------
159 | ### 参与插件贡献
160 | **代码pr**:理论上不允许任何人往`master`分支合并代码,如果你有重大改动,请联系我的邮箱(`webwork.s@qq.com`)或者qq(`370306150`),我会专门为你建立一条分支。
161 |
162 | **其他**:[鸣谢](/acknowledgement/)对插件做出贡献者
163 | ### ts 支持
164 | index.d.ts。目前,该文件由@TuiMao233提供。希望更多的人可以参与进来,pr请提到`request-ts`分支。request-ts
165 |
166 | # 深入
167 |
168 |
169 | 开发理念
170 | ------------
171 | ...
172 |
--------------------------------------------------------------------------------
/src/lib/core/Request.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @Class Request
3 | * @description luch-request http请求插件
4 | * @Author lu-ch
5 | * @Email webwork.s@qq.com
6 | * 文档: https://www.quanzhan.co/luch-request/
7 | * github: https://github.com/lei-mu/luch-request
8 | * DCloud: http://ext.dcloud.net.cn/plugin?id=392
9 | */
10 |
11 |
12 | import dispatchRequest from './dispatchRequest'
13 | import InterceptorManager from './InterceptorManager'
14 | import mergeConfig from './mergeConfig'
15 | import defaults from './defaults'
16 | import { isPlainObject } from '../utils'
17 | import clone from '../utils/clone'
18 |
19 | export default class Request {
20 | /**
21 | * @param {Object} arg - 全局配置
22 | * @param {String} arg.baseURL - 全局根路径
23 | * @param {Object} arg.header - 全局header
24 | * @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
25 | * @param {String} arg.dataType = [json] - 全局默认的dataType
26 | * @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
27 | * @param {Object} arg.custom - 全局默认的自定义参数
28 | * @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
29 | * @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
30 | * @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
31 | * @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
32 | * @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
33 | */
34 | constructor(arg = {}) {
35 | if (!isPlainObject(arg)) {
36 | arg = {}
37 | console.warn('设置全局参数必须接收一个Object')
38 | }
39 | this.config = clone({...defaults, ...arg})
40 | this.interceptors = {
41 | request: new InterceptorManager(),
42 | response: new InterceptorManager()
43 | }
44 | }
45 |
46 | /**
47 | * @Function
48 | * @param {Request~setConfigCallback} f - 设置全局默认配置
49 | */
50 | setConfig(f) {
51 | this.config = f(this.config)
52 | }
53 |
54 | middleware(config) {
55 | config = mergeConfig(this.config, config)
56 | let chain = [dispatchRequest, undefined]
57 | let promise = Promise.resolve(config)
58 |
59 | this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
60 | chain.unshift(interceptor.fulfilled, interceptor.rejected)
61 | })
62 |
63 | this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
64 | chain.push(interceptor.fulfilled, interceptor.rejected)
65 | })
66 |
67 | while (chain.length) {
68 | promise = promise.then(chain.shift(), chain.shift())
69 | }
70 |
71 | return promise
72 | }
73 |
74 | /**
75 | * @Function
76 | * @param {Object} config - 请求配置项
77 | * @prop {String} options.url - 请求路径
78 | * @prop {Object} options.data - 请求参数
79 | * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
80 | * @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
81 | * @prop {Object} [options.header = config.header] - 请求header
82 | * @prop {Object} [options.method = config.method] - 请求方法
83 | * @returns {Promise}
84 | */
85 | request(config = {}) {
86 | return this.middleware(config)
87 | }
88 |
89 | get(url, options = {}) {
90 | return this.middleware({
91 | url,
92 | method: 'GET',
93 | ...options
94 | })
95 | }
96 |
97 | post(url, data, options = {}) {
98 | return this.middleware({
99 | url,
100 | data,
101 | method: 'POST',
102 | ...options
103 | })
104 | }
105 |
106 | // #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD
107 | put(url, data, options = {}) {
108 | return this.middleware({
109 | url,
110 | data,
111 | method: 'PUT',
112 | ...options
113 | })
114 | }
115 |
116 | // #endif
117 |
118 | // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
119 | delete(url, data, options = {}) {
120 | return this.middleware({
121 | url,
122 | data,
123 | method: 'DELETE',
124 | ...options
125 | })
126 | }
127 |
128 | // #endif
129 |
130 | // #ifdef H5 || MP-WEIXIN
131 | connect(url, data, options = {}) {
132 | return this.middleware({
133 | url,
134 | data,
135 | method: 'CONNECT',
136 | ...options
137 | })
138 | }
139 |
140 | // #endif
141 |
142 | // #ifdef H5 || MP-WEIXIN || MP-BAIDU
143 | head(url, data, options = {}) {
144 | return this.middleware({
145 | url,
146 | data,
147 | method: 'HEAD',
148 | ...options
149 | })
150 | }
151 |
152 | // #endif
153 |
154 | // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
155 | options(url, data, options = {}) {
156 | return this.middleware({
157 | url,
158 | data,
159 | method: 'OPTIONS',
160 | ...options
161 | })
162 | }
163 |
164 | // #endif
165 |
166 | // #ifdef H5 || MP-WEIXIN
167 | trace(url, data, options = {}) {
168 | return this.middleware({
169 | url,
170 | data,
171 | method: 'TRACE',
172 | ...options
173 | })
174 | }
175 |
176 | // #endif
177 |
178 | upload(url, config = {}) {
179 | config.url = url
180 | config.method = 'UPLOAD'
181 | return this.middleware(config)
182 | }
183 |
184 | download(url, config = {}) {
185 | config.url = url
186 | config.method = 'DOWNLOAD'
187 | return this.middleware(config)
188 | }
189 |
190 | get version () {
191 | return '3.1.0'
192 | }
193 | }
194 |
195 |
196 | /**
197 | * setConfig回调
198 | * @return {Object} - 返回操作后的config
199 | * @callback Request~setConfigCallback
200 | * @param {Object} config - 全局默认config
201 | */
202 |
--------------------------------------------------------------------------------
/DCloud/luch-request/core/Request.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @Class Request
3 | * @description luch-request http请求插件
4 | * @Author lu-ch
5 | * @Email webwork.s@qq.com
6 | * 文档: https://www.quanzhan.co/luch-request/
7 | * github: https://github.com/lei-mu/luch-request
8 | * DCloud: http://ext.dcloud.net.cn/plugin?id=392
9 | */
10 |
11 |
12 | import dispatchRequest from './dispatchRequest'
13 | import InterceptorManager from './InterceptorManager'
14 | import mergeConfig from './mergeConfig'
15 | import defaults from './defaults'
16 | import { isPlainObject } from '../utils'
17 | import clone from '../utils/clone'
18 |
19 | export default class Request {
20 | /**
21 | * @param {Object} arg - 全局配置
22 | * @param {String} arg.baseURL - 全局根路径
23 | * @param {Object} arg.header - 全局header
24 | * @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
25 | * @param {String} arg.dataType = [json] - 全局默认的dataType
26 | * @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
27 | * @param {Object} arg.custom - 全局默认的自定义参数
28 | * @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
29 | * @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
30 | * @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
31 | * @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
32 | * @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
33 | */
34 | constructor(arg = {}) {
35 | if (!isPlainObject(arg)) {
36 | arg = {}
37 | console.warn('设置全局参数必须接收一个Object')
38 | }
39 | this.config = clone({...defaults, ...arg})
40 | this.interceptors = {
41 | request: new InterceptorManager(),
42 | response: new InterceptorManager()
43 | }
44 | }
45 |
46 | /**
47 | * @Function
48 | * @param {Request~setConfigCallback} f - 设置全局默认配置
49 | */
50 | setConfig(f) {
51 | this.config = f(this.config)
52 | }
53 |
54 | middleware(config) {
55 | config = mergeConfig(this.config, config)
56 | let chain = [dispatchRequest, undefined]
57 | let promise = Promise.resolve(config)
58 |
59 | this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
60 | chain.unshift(interceptor.fulfilled, interceptor.rejected)
61 | })
62 |
63 | this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
64 | chain.push(interceptor.fulfilled, interceptor.rejected)
65 | })
66 |
67 | while (chain.length) {
68 | promise = promise.then(chain.shift(), chain.shift())
69 | }
70 |
71 | return promise
72 | }
73 |
74 | /**
75 | * @Function
76 | * @param {Object} config - 请求配置项
77 | * @prop {String} options.url - 请求路径
78 | * @prop {Object} options.data - 请求参数
79 | * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
80 | * @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
81 | * @prop {Object} [options.header = config.header] - 请求header
82 | * @prop {Object} [options.method = config.method] - 请求方法
83 | * @returns {Promise}
84 | */
85 | request(config = {}) {
86 | return this.middleware(config)
87 | }
88 |
89 | get(url, options = {}) {
90 | return this.middleware({
91 | url,
92 | method: 'GET',
93 | ...options
94 | })
95 | }
96 |
97 | post(url, data, options = {}) {
98 | return this.middleware({
99 | url,
100 | data,
101 | method: 'POST',
102 | ...options
103 | })
104 | }
105 |
106 | // #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD
107 | put(url, data, options = {}) {
108 | return this.middleware({
109 | url,
110 | data,
111 | method: 'PUT',
112 | ...options
113 | })
114 | }
115 |
116 | // #endif
117 |
118 | // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
119 | delete(url, data, options = {}) {
120 | return this.middleware({
121 | url,
122 | data,
123 | method: 'DELETE',
124 | ...options
125 | })
126 | }
127 |
128 | // #endif
129 |
130 | // #ifdef H5 || MP-WEIXIN
131 | connect(url, data, options = {}) {
132 | return this.middleware({
133 | url,
134 | data,
135 | method: 'CONNECT',
136 | ...options
137 | })
138 | }
139 |
140 | // #endif
141 |
142 | // #ifdef H5 || MP-WEIXIN || MP-BAIDU
143 | head(url, data, options = {}) {
144 | return this.middleware({
145 | url,
146 | data,
147 | method: 'HEAD',
148 | ...options
149 | })
150 | }
151 |
152 | // #endif
153 |
154 | // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
155 | options(url, data, options = {}) {
156 | return this.middleware({
157 | url,
158 | data,
159 | method: 'OPTIONS',
160 | ...options
161 | })
162 | }
163 |
164 | // #endif
165 |
166 | // #ifdef H5 || MP-WEIXIN
167 | trace(url, data, options = {}) {
168 | return this.middleware({
169 | url,
170 | data,
171 | method: 'TRACE',
172 | ...options
173 | })
174 | }
175 |
176 | // #endif
177 |
178 | upload(url, config = {}) {
179 | config.url = url
180 | config.method = 'UPLOAD'
181 | return this.middleware(config)
182 | }
183 |
184 | download(url, config = {}) {
185 | config.url = url
186 | config.method = 'DOWNLOAD'
187 | return this.middleware(config)
188 | }
189 |
190 | get version () {
191 | return '3.1.0'
192 | }
193 | }
194 |
195 |
196 | /**
197 | * setConfig回调
198 | * @return {Object} - 返回操作后的config
199 | * @callback Request~setConfigCallback
200 | * @param {Object} config - 全局默认config
201 | */
202 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/core/Request.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @Class Request
3 | * @description luch-request http请求插件
4 | * @Author lu-ch
5 | * @Email webwork.s@qq.com
6 | * 文档: https://www.quanzhan.co/luch-request/
7 | * github: https://github.com/lei-mu/luch-request
8 | * DCloud: http://ext.dcloud.net.cn/plugin?id=392
9 | */
10 |
11 |
12 | import dispatchRequest from './dispatchRequest'
13 | import InterceptorManager from './InterceptorManager'
14 | import mergeConfig from './mergeConfig'
15 | import defaults from './defaults'
16 | import { isPlainObject } from '../utils'
17 | import clone from '../utils/clone'
18 |
19 | export default class Request {
20 | /**
21 | * @param {Object} arg - 全局配置
22 | * @param {String} arg.baseURL - 全局根路径
23 | * @param {Object} arg.header - 全局header
24 | * @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
25 | * @param {String} arg.dataType = [json] - 全局默认的dataType
26 | * @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
27 | * @param {Object} arg.custom - 全局默认的自定义参数
28 | * @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
29 | * @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
30 | * @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
31 | * @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
32 | * @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
33 | */
34 | constructor(arg = {}) {
35 | if (!isPlainObject(arg)) {
36 | arg = {}
37 | console.warn('设置全局参数必须接收一个Object')
38 | }
39 | this.config = clone({...defaults, ...arg})
40 | this.interceptors = {
41 | request: new InterceptorManager(),
42 | response: new InterceptorManager()
43 | }
44 | }
45 |
46 | /**
47 | * @Function
48 | * @param {Request~setConfigCallback} f - 设置全局默认配置
49 | */
50 | setConfig(f) {
51 | this.config = f(this.config)
52 | }
53 |
54 | middleware(config) {
55 | config = mergeConfig(this.config, config)
56 | let chain = [dispatchRequest, undefined]
57 | let promise = Promise.resolve(config)
58 |
59 | this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
60 | chain.unshift(interceptor.fulfilled, interceptor.rejected)
61 | })
62 |
63 | this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
64 | chain.push(interceptor.fulfilled, interceptor.rejected)
65 | })
66 |
67 | while (chain.length) {
68 | promise = promise.then(chain.shift(), chain.shift())
69 | }
70 |
71 | return promise
72 | }
73 |
74 | /**
75 | * @Function
76 | * @param {Object} config - 请求配置项
77 | * @prop {String} options.url - 请求路径
78 | * @prop {Object} options.data - 请求参数
79 | * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
80 | * @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
81 | * @prop {Object} [options.header = config.header] - 请求header
82 | * @prop {Object} [options.method = config.method] - 请求方法
83 | * @returns {Promise}
84 | */
85 | request(config = {}) {
86 | return this.middleware(config)
87 | }
88 |
89 | get(url, options = {}) {
90 | return this.middleware({
91 | url,
92 | method: 'GET',
93 | ...options
94 | })
95 | }
96 |
97 | post(url, data, options = {}) {
98 | return this.middleware({
99 | url,
100 | data,
101 | method: 'POST',
102 | ...options
103 | })
104 | }
105 |
106 | // #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD
107 | put(url, data, options = {}) {
108 | return this.middleware({
109 | url,
110 | data,
111 | method: 'PUT',
112 | ...options
113 | })
114 | }
115 |
116 | // #endif
117 |
118 | // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
119 | delete(url, data, options = {}) {
120 | return this.middleware({
121 | url,
122 | data,
123 | method: 'DELETE',
124 | ...options
125 | })
126 | }
127 |
128 | // #endif
129 |
130 | // #ifdef H5 || MP-WEIXIN
131 | connect(url, data, options = {}) {
132 | return this.middleware({
133 | url,
134 | data,
135 | method: 'CONNECT',
136 | ...options
137 | })
138 | }
139 |
140 | // #endif
141 |
142 | // #ifdef H5 || MP-WEIXIN || MP-BAIDU
143 | head(url, data, options = {}) {
144 | return this.middleware({
145 | url,
146 | data,
147 | method: 'HEAD',
148 | ...options
149 | })
150 | }
151 |
152 | // #endif
153 |
154 | // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
155 | options(url, data, options = {}) {
156 | return this.middleware({
157 | url,
158 | data,
159 | method: 'OPTIONS',
160 | ...options
161 | })
162 | }
163 |
164 | // #endif
165 |
166 | // #ifdef H5 || MP-WEIXIN
167 | trace(url, data, options = {}) {
168 | return this.middleware({
169 | url,
170 | data,
171 | method: 'TRACE',
172 | ...options
173 | })
174 | }
175 |
176 | // #endif
177 |
178 | upload(url, config = {}) {
179 | config.url = url
180 | config.method = 'UPLOAD'
181 | return this.middleware(config)
182 | }
183 |
184 | download(url, config = {}) {
185 | config.url = url
186 | config.method = 'DOWNLOAD'
187 | return this.middleware(config)
188 | }
189 |
190 | get version () {
191 | return '3.1.0'
192 | }
193 | }
194 |
195 |
196 | /**
197 | * setConfig回调
198 | * @return {Object} - 返回操作后的config
199 | * @callback Request~setConfigCallback
200 | * @param {Object} config - 全局默认config
201 | */
202 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/core/Request.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @Class Request
3 | * @description luch-request http请求插件
4 | * @Author lu-ch
5 | * @Email webwork.s@qq.com
6 | * 文档: https://www.quanzhan.co/luch-request/
7 | * github: https://github.com/lei-mu/luch-request
8 | * DCloud: http://ext.dcloud.net.cn/plugin?id=392
9 | */
10 |
11 |
12 | import dispatchRequest from './dispatchRequest'
13 | import InterceptorManager from './InterceptorManager'
14 | import mergeConfig from './mergeConfig'
15 | import defaults from './defaults'
16 | import { isPlainObject } from '../utils'
17 | import clone from '../utils/clone'
18 |
19 | export default class Request {
20 | /**
21 | * @param {Object} arg - 全局配置
22 | * @param {String} arg.baseURL - 全局根路径
23 | * @param {Object} arg.header - 全局header
24 | * @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
25 | * @param {String} arg.dataType = [json] - 全局默认的dataType
26 | * @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
27 | * @param {Object} arg.custom - 全局默认的自定义参数
28 | * @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
29 | * @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
30 | * @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
31 | * @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
32 | * @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
33 | */
34 | constructor(arg = {}) {
35 | if (!isPlainObject(arg)) {
36 | arg = {}
37 | console.warn('设置全局参数必须接收一个Object')
38 | }
39 | this.config = clone({...defaults, ...arg})
40 | this.interceptors = {
41 | request: new InterceptorManager(),
42 | response: new InterceptorManager()
43 | }
44 | }
45 |
46 | /**
47 | * @Function
48 | * @param {Request~setConfigCallback} f - 设置全局默认配置
49 | */
50 | setConfig(f) {
51 | this.config = f(this.config)
52 | }
53 |
54 | middleware(config) {
55 | config = mergeConfig(this.config, config)
56 | let chain = [dispatchRequest, undefined]
57 | let promise = Promise.resolve(config)
58 |
59 | this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
60 | chain.unshift(interceptor.fulfilled, interceptor.rejected)
61 | })
62 |
63 | this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
64 | chain.push(interceptor.fulfilled, interceptor.rejected)
65 | })
66 |
67 | while (chain.length) {
68 | promise = promise.then(chain.shift(), chain.shift())
69 | }
70 |
71 | return promise
72 | }
73 |
74 | /**
75 | * @Function
76 | * @param {Object} config - 请求配置项
77 | * @prop {String} options.url - 请求路径
78 | * @prop {Object} options.data - 请求参数
79 | * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
80 | * @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
81 | * @prop {Object} [options.header = config.header] - 请求header
82 | * @prop {Object} [options.method = config.method] - 请求方法
83 | * @returns {Promise}
84 | */
85 | request(config = {}) {
86 | return this.middleware(config)
87 | }
88 |
89 | get(url, options = {}) {
90 | return this.middleware({
91 | url,
92 | method: 'GET',
93 | ...options
94 | })
95 | }
96 |
97 | post(url, data, options = {}) {
98 | return this.middleware({
99 | url,
100 | data,
101 | method: 'POST',
102 | ...options
103 | })
104 | }
105 |
106 | // #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD
107 | put(url, data, options = {}) {
108 | return this.middleware({
109 | url,
110 | data,
111 | method: 'PUT',
112 | ...options
113 | })
114 | }
115 |
116 | // #endif
117 |
118 | // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
119 | delete(url, data, options = {}) {
120 | return this.middleware({
121 | url,
122 | data,
123 | method: 'DELETE',
124 | ...options
125 | })
126 | }
127 |
128 | // #endif
129 |
130 | // #ifdef H5 || MP-WEIXIN
131 | connect(url, data, options = {}) {
132 | return this.middleware({
133 | url,
134 | data,
135 | method: 'CONNECT',
136 | ...options
137 | })
138 | }
139 |
140 | // #endif
141 |
142 | // #ifdef H5 || MP-WEIXIN || MP-BAIDU
143 | head(url, data, options = {}) {
144 | return this.middleware({
145 | url,
146 | data,
147 | method: 'HEAD',
148 | ...options
149 | })
150 | }
151 |
152 | // #endif
153 |
154 | // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
155 | options(url, data, options = {}) {
156 | return this.middleware({
157 | url,
158 | data,
159 | method: 'OPTIONS',
160 | ...options
161 | })
162 | }
163 |
164 | // #endif
165 |
166 | // #ifdef H5 || MP-WEIXIN
167 | trace(url, data, options = {}) {
168 | return this.middleware({
169 | url,
170 | data,
171 | method: 'TRACE',
172 | ...options
173 | })
174 | }
175 |
176 | // #endif
177 |
178 | upload(url, config = {}) {
179 | config.url = url
180 | config.method = 'UPLOAD'
181 | return this.middleware(config)
182 | }
183 |
184 | download(url, config = {}) {
185 | config.url = url
186 | config.method = 'DOWNLOAD'
187 | return this.middleware(config)
188 | }
189 |
190 | get version () {
191 | return '3.1.0'
192 | }
193 | }
194 |
195 |
196 | /**
197 | * setConfig回调
198 | * @return {Object} - 返回操作后的config
199 | * @callback Request~setConfigCallback
200 | * @param {Object} config - 全局默认config
201 | */
202 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 | /* Basic Options */
5 | // "incremental": true, /* Enable incremental compilation */
6 | "target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
7 | "module": "ES2015", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
8 | // "lib": [], /* Specify library files to be included in the compilation. */
9 | // "allowJs": true, /* Allow javascript files to be compiled. */
10 | // "checkJs": true, /* Report errors in .js files. */
11 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
12 | "declaration": true, /* Generates corresponding '.d.ts' file. */
13 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
14 | // "sourceMap": true, /* Generates corresponding '.map' file. */
15 | // "outFile": "./", /* Concatenate and emit output to single file. */
16 | // "outDir": "../test-template/node_modules/uni-draw-poster", /* Redirect output structure to the directory. */
17 | "outDir": "../dist", /* Redirect output structure to the directory. */
18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
19 | // "composite": true, /* Enable project compilation */
20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
21 | // "removeComments": true, /* Do not emit comments to output. */
22 | // "noEmit": true, /* Do not emit outputs. */
23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */
24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26 | /* Strict Type-Checking Options */
27 | "strict": true, /* Enable all strict type-checking options. */
28 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
29 | // "strictNullChecks": true, /* Enable strict null checks. */
30 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */
31 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
32 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
33 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
34 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
35 | /* Additional Checks */
36 | // "noUnusedLocals": true, /* Report errors on unused locals. */
37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
40 | /* Module Resolution Options */
41 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
42 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
43 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
44 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
45 | "types": [
46 | "@dcloudio/types"
47 | ], /* Type declaration files to be included in compilation. */
48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
49 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
51 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
52 | /* Source Map Options */
53 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
54 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
55 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
56 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
57 | /* Experimental Options */
58 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
59 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
60 | /* Advanced Options */
61 | "skipLibCheck": true, /* Skip type checking of declaration files. */
62 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
63 | }
64 | }
--------------------------------------------------------------------------------
/src/lib/luch-request.d.ts:
--------------------------------------------------------------------------------
1 | export type HttpTask = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask;
2 |
3 | export type HttpRequestTask = UniApp.RequestTask;
4 |
5 | export type HttpUploadTask = UniApp.UploadTask;
6 |
7 | export type HttpDownloadTask = UniApp.DownloadTask;
8 |
9 | export type HttpMethod =
10 | "GET"
11 | | "POST"
12 | | "PUT"
13 | | "DELETE"
14 | | "CONNECT"
15 | | "HEAD"
16 | | "OPTIONS"
17 | | "TRACE"
18 | | "UPLOAD"
19 | | "DOWNLOAD";
20 |
21 | export type HttpRequestHeader = Record;
22 |
23 | export type HttpParams = Record;
24 |
25 | export type HttpData = Record;
26 |
27 | export type HttpResponseType = 'arraybuffer' | 'text';
28 |
29 | export type HttpCustom = Record;
30 |
31 | export type HttpFileType = 'image' | 'video' | 'audio';
32 |
33 | export type HttpFormData = Record;
34 |
35 | export type HttpResponseHeader = Record & {
36 | "set-cookie"?: string[]
37 | };
38 |
39 | export interface HttpRequestConfig {
40 | /** @desc 请求服务器接口地址 */
41 | url?: string;
42 | /** @desc 请求方式,默认为 GET */
43 | method?: HttpMethod;
44 | /** @desc 请求基地址 */
45 | baseURL?: string;
46 | /** @desc 请求头信息,不能设置 Referer,App、H5 端会自动带上 cookie,且 H5 端不可手动修改 */
47 | header?: HttpRequestHeader;
48 | /** @desc 请求查询参数,自动拼接为查询字符串 */
49 | params?: HttpParams;
50 | /** @desc 请求体参数 */
51 | data?: HttpData;
52 | /** @desc 超时时间,单位 ms,默认为 60000,仅 H5 (HBuilderX 2.9.9+)、APP (HBuilderX 2.9.9+)、微信小程序 (2.10.0)、支付宝小程序支持 */
53 | timeout?: number;
54 | /** @desc 跨域请求时是否携带凭证 (cookies),默认为 false,仅 H5 (HBuilderX 2.6.15+) 支持 */
55 | withCredentials?: boolean;
56 | /** @desc 设置响应的数据类型,支付宝小程序不支持 */
57 | responseType?: HttpResponseType;
58 | /** @desc 全局自定义验证器 */
59 | validateStatus?: ((statusCode: number) => boolean) | null;
60 |
61 |
62 | /** params 参数自定义处理 */
63 | paramsSerializer?: (params: AnyObject) => string | void;
64 |
65 | /** @desc 默认为 json,如果设为 json,会尝试对返回的数据做一次 JSON.parse */
66 | dataType?: string;
67 | /** @desc DNS 解析时是否优先使用 ipv4,默认为 false,仅 App-Android (HBuilderX 2.8.0+) 支持 */
68 | firstIpv4?: boolean;
69 | /** @desc 是否验证 SSL 证书,默认为 true,仅 App-Android (HBuilderX 2.3.3+) 支持 */
70 | sslVerify?: boolean;
71 |
72 | /** @desc 开启 http2;微信小程序 */
73 | enableHttp2?: boolean;
74 |
75 | /** @desc 开启 quic;微信小程序 */
76 | enableQuic?: boolean;
77 | /** @desc 开启 cache;微信小程序、字节跳动小程序 2.31.0+ */
78 | enableCache?: boolean;
79 | /** @desc 开启 httpDNS;微信小程序 */
80 | enableHttpDNS?: boolean;
81 | /** @desc httpDNS 服务商;微信小程序 */
82 | httpDNSServiceId?: string;
83 | /** @desc 开启 transfer-encoding chunked;微信小程序 */
84 | enableChunked?: boolean;
85 | /** @desc wifi下使用移动网络发送请求;微信小程序 */
86 | forceCellularNetwork?: boolean;
87 | /** @desc 开启后可在headers中编辑cookie;支付宝小程序 10.2.33+ */
88 | enableCookie?: boolean;
89 | /** @desc 是否开启云加速;百度小程序 3.310.11+ */
90 | cloudCache?: boolean | object;
91 | /** @desc 控制当前请求是否延时至首屏内容渲染后发送;百度小程序 3.310.11+ */
92 | defer?: boolean;
93 |
94 | /** @desc 自定义参数 */
95 | custom?: HttpCustom;
96 |
97 | /** @desc 返回当前请求的 task 和 options,不要在这里修改 options */
98 | getTask?: (task: T, options: HttpRequestConfig) => void;
99 |
100 | /** @desc 需要上传的文件列表,使用 files 时,filePath 和 name 不生效,仅支持 App、H5 (2.6.15+) */
101 | files?: { name?: string; file?: File; uri: string; }[];
102 | /** @desc 文件类型,仅支付宝小程序支持且为必填项 */
103 | fileType?: HttpFileType;
104 | /** @desc 要上传的文件对象,仅 H5 (2.6.15+) 支持 */
105 | file?: File;
106 | /** @desc 要上传文件资源的路径,使用 files 时,filePath 和 name 不生效 */
107 | filePath?: string;
108 | /** @desc 文件对应的 key,开发者在服务器端通过这个 key 可以获取到文件二进制内容,使用 files 时,filePath 和 name 不生效 */
109 | name?: string;
110 | /** @desc 请求中其他额外的 form data */
111 | formData?: HttpFormData;
112 | }
113 |
114 | export interface HttpResponse {
115 | data: T;
116 | statusCode: number;
117 | header: HttpResponseHeader;
118 | config: HttpRequestConfig;
119 | cookies: string[];
120 | errMsg: string;
121 | rawData: any;
122 | }
123 |
124 | export interface HttpUploadResponse {
125 | data: T;
126 | statusCode: number;
127 | config: HttpRequestConfig;
128 | errMsg: string;
129 | rawData: any;
130 | }
131 |
132 | export interface HttpDownloadResponse extends HttpResponse {
133 | tempFilePath: string;
134 | apFilePath?: string;
135 | filePath?: string;
136 | fileContent?: string;
137 | }
138 |
139 | export interface HttpError {
140 | data?: T;
141 | statusCode?: number;
142 | header?: HttpResponseHeader;
143 | config: HttpRequestConfig;
144 | cookies?: string[];
145 | errMsg: string;
146 | }
147 |
148 | export interface HttpPromise extends Promise> {
149 | }
150 |
151 | export interface HttpInterceptorManager {
152 | use(onFulfilled?: (value: V) => V | Promise, onRejected?: (error: E) => T | Promise): void;
153 |
154 | eject(id: number): void;
155 | }
156 |
157 | export abstract class HttpRequestAbstract {
158 | constructor(config?: HttpRequestConfig);
159 |
160 | interceptors: {
161 | request: HttpInterceptorManager;
162 | response: HttpInterceptorManager;
163 | }
164 |
165 | request, D = HttpRequestTask>(config: HttpRequestConfig): Promise;
166 |
167 | get, D = HttpRequestTask>(url: string, config?: HttpRequestConfig): Promise;
168 |
169 | delete, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
170 |
171 | head, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
172 |
173 | options, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
174 |
175 | post, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
176 |
177 | put, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
178 |
179 | config: HttpRequestConfig;
180 |
181 | setConfig(onSend: (config: HttpRequestConfig) => HttpRequestConfig): void;
182 |
183 | connect, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
184 |
185 | trace, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
186 |
187 | upload, D = HttpUploadTask>(url: string, config?: HttpRequestConfig): Promise;
188 |
189 | download, D = HttpDownloadTask>(url: string, config?: HttpRequestConfig): Promise;
190 |
191 | middleware, D = HttpTask>(config: HttpRequestConfig): Promise;
192 | }
193 |
194 | declare class HttpRequest extends HttpRequestAbstract {
195 | }
196 |
197 | export default HttpRequest;
198 |
--------------------------------------------------------------------------------
/DCloud/luch-request/index.d.ts:
--------------------------------------------------------------------------------
1 | export type HttpTask = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask;
2 |
3 | export type HttpRequestTask = UniApp.RequestTask;
4 |
5 | export type HttpUploadTask = UniApp.UploadTask;
6 |
7 | export type HttpDownloadTask = UniApp.DownloadTask;
8 |
9 | export type HttpMethod =
10 | "GET"
11 | | "POST"
12 | | "PUT"
13 | | "DELETE"
14 | | "CONNECT"
15 | | "HEAD"
16 | | "OPTIONS"
17 | | "TRACE"
18 | | "UPLOAD"
19 | | "DOWNLOAD";
20 |
21 | export type HttpRequestHeader = Record;
22 |
23 | export type HttpParams = Record;
24 |
25 | export type HttpData = Record;
26 |
27 | export type HttpResponseType = 'arraybuffer' | 'text';
28 |
29 | export type HttpCustom = Record;
30 |
31 | export type HttpFileType = 'image' | 'video' | 'audio';
32 |
33 | export type HttpFormData = Record;
34 |
35 | export type HttpResponseHeader = Record & {
36 | "set-cookie"?: string[]
37 | };
38 |
39 | export interface HttpRequestConfig {
40 | /** @desc 请求服务器接口地址 */
41 | url?: string;
42 | /** @desc 请求方式,默认为 GET */
43 | method?: HttpMethod;
44 | /** @desc 请求基地址 */
45 | baseURL?: string;
46 | /** @desc 请求头信息,不能设置 Referer,App、H5 端会自动带上 cookie,且 H5 端不可手动修改 */
47 | header?: HttpRequestHeader;
48 | /** @desc 请求查询参数,自动拼接为查询字符串 */
49 | params?: HttpParams;
50 | /** @desc 请求体参数 */
51 | data?: HttpData;
52 | /** @desc 超时时间,单位 ms,默认为 60000,仅 H5 (HBuilderX 2.9.9+)、APP (HBuilderX 2.9.9+)、微信小程序 (2.10.0)、支付宝小程序支持 */
53 | timeout?: number;
54 | /** @desc 跨域请求时是否携带凭证 (cookies),默认为 false,仅 H5 (HBuilderX 2.6.15+) 支持 */
55 | withCredentials?: boolean;
56 | /** @desc 设置响应的数据类型,支付宝小程序不支持 */
57 | responseType?: HttpResponseType;
58 | /** @desc 全局自定义验证器 */
59 | validateStatus?: ((statusCode: number) => boolean) | null;
60 |
61 |
62 | /** params 参数自定义处理 */
63 | paramsSerializer?: (params: AnyObject) => string | void;
64 |
65 | /** @desc 默认为 json,如果设为 json,会尝试对返回的数据做一次 JSON.parse */
66 | dataType?: string;
67 | /** @desc DNS 解析时是否优先使用 ipv4,默认为 false,仅 App-Android (HBuilderX 2.8.0+) 支持 */
68 | firstIpv4?: boolean;
69 | /** @desc 是否验证 SSL 证书,默认为 true,仅 App-Android (HBuilderX 2.3.3+) 支持 */
70 | sslVerify?: boolean;
71 |
72 | /** @desc 开启 http2;微信小程序 */
73 | enableHttp2?: boolean;
74 |
75 | /** @desc 开启 quic;微信小程序 */
76 | enableQuic?: boolean;
77 | /** @desc 开启 cache;微信小程序、字节跳动小程序 2.31.0+ */
78 | enableCache?: boolean;
79 | /** @desc 开启 httpDNS;微信小程序 */
80 | enableHttpDNS?: boolean;
81 | /** @desc httpDNS 服务商;微信小程序 */
82 | httpDNSServiceId?: string;
83 | /** @desc 开启 transfer-encoding chunked;微信小程序 */
84 | enableChunked?: boolean;
85 | /** @desc wifi下使用移动网络发送请求;微信小程序 */
86 | forceCellularNetwork?: boolean;
87 | /** @desc 开启后可在headers中编辑cookie;支付宝小程序 10.2.33+ */
88 | enableCookie?: boolean;
89 | /** @desc 是否开启云加速;百度小程序 3.310.11+ */
90 | cloudCache?: boolean | object;
91 | /** @desc 控制当前请求是否延时至首屏内容渲染后发送;百度小程序 3.310.11+ */
92 | defer?: boolean;
93 |
94 | /** @desc 自定义参数 */
95 | custom?: HttpCustom;
96 |
97 | /** @desc 返回当前请求的 task 和 options,不要在这里修改 options */
98 | getTask?: (task: T, options: HttpRequestConfig) => void;
99 |
100 | /** @desc 需要上传的文件列表,使用 files 时,filePath 和 name 不生效,仅支持 App、H5 (2.6.15+) */
101 | files?: { name?: string; file?: File; uri: string; }[];
102 | /** @desc 文件类型,仅支付宝小程序支持且为必填项 */
103 | fileType?: HttpFileType;
104 | /** @desc 要上传的文件对象,仅 H5 (2.6.15+) 支持 */
105 | file?: File;
106 | /** @desc 要上传文件资源的路径,使用 files 时,filePath 和 name 不生效 */
107 | filePath?: string;
108 | /** @desc 文件对应的 key,开发者在服务器端通过这个 key 可以获取到文件二进制内容,使用 files 时,filePath 和 name 不生效 */
109 | name?: string;
110 | /** @desc 请求中其他额外的 form data */
111 | formData?: HttpFormData;
112 | }
113 |
114 | export interface HttpResponse {
115 | data: T;
116 | statusCode: number;
117 | header: HttpResponseHeader;
118 | config: HttpRequestConfig;
119 | cookies: string[];
120 | errMsg: string;
121 | rawData: any;
122 | }
123 |
124 | export interface HttpUploadResponse {
125 | data: T;
126 | statusCode: number;
127 | config: HttpRequestConfig;
128 | errMsg: string;
129 | rawData: any;
130 | }
131 |
132 | export interface HttpDownloadResponse extends HttpResponse {
133 | tempFilePath: string;
134 | apFilePath?: string;
135 | filePath?: string;
136 | fileContent?: string;
137 | }
138 |
139 | export interface HttpError {
140 | data?: T;
141 | statusCode?: number;
142 | header?: HttpResponseHeader;
143 | config: HttpRequestConfig;
144 | cookies?: string[];
145 | errMsg: string;
146 | }
147 |
148 | export interface HttpPromise extends Promise> {
149 | }
150 |
151 | export interface HttpInterceptorManager {
152 | use(onFulfilled?: (value: V) => V | Promise, onRejected?: (error: E) => T | Promise): void;
153 |
154 | eject(id: number): void;
155 | }
156 |
157 | export abstract class HttpRequestAbstract {
158 | constructor(config?: HttpRequestConfig);
159 |
160 | interceptors: {
161 | request: HttpInterceptorManager;
162 | response: HttpInterceptorManager;
163 | }
164 |
165 | request, D = HttpRequestTask>(config: HttpRequestConfig): Promise;
166 |
167 | get, D = HttpRequestTask>(url: string, config?: HttpRequestConfig): Promise;
168 |
169 | delete, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
170 |
171 | head, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
172 |
173 | options, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
174 |
175 | post, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
176 |
177 | put, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
178 |
179 | config: HttpRequestConfig;
180 |
181 | setConfig(onSend: (config: HttpRequestConfig) => HttpRequestConfig): void;
182 |
183 | connect, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
184 |
185 | trace, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
186 |
187 | upload, D = HttpUploadTask>(url: string, config?: HttpRequestConfig): Promise;
188 |
189 | download, D = HttpDownloadTask>(url: string, config?: HttpRequestConfig): Promise;
190 |
191 | middleware, D = HttpTask>(config: HttpRequestConfig): Promise;
192 | }
193 |
194 | declare class HttpRequest extends HttpRequestAbstract {
195 | }
196 |
197 | export default HttpRequest;
198 |
--------------------------------------------------------------------------------
/test/dev-test/utils/luch-request/index.d.ts:
--------------------------------------------------------------------------------
1 | export type HttpTask = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask;
2 |
3 | export type HttpRequestTask = UniApp.RequestTask;
4 |
5 | export type HttpUploadTask = UniApp.UploadTask;
6 |
7 | export type HttpDownloadTask = UniApp.DownloadTask;
8 |
9 | export type HttpMethod =
10 | "GET"
11 | | "POST"
12 | | "PUT"
13 | | "DELETE"
14 | | "CONNECT"
15 | | "HEAD"
16 | | "OPTIONS"
17 | | "TRACE"
18 | | "UPLOAD"
19 | | "DOWNLOAD";
20 |
21 | export type HttpRequestHeader = Record;
22 |
23 | export type HttpParams = Record;
24 |
25 | export type HttpData = Record;
26 |
27 | export type HttpResponseType = 'arraybuffer' | 'text';
28 |
29 | export type HttpCustom = Record;
30 |
31 | export type HttpFileType = 'image' | 'video' | 'audio';
32 |
33 | export type HttpFormData = Record;
34 |
35 | export type HttpResponseHeader = Record & {
36 | "set-cookie"?: string[]
37 | };
38 |
39 | export interface HttpRequestConfig {
40 | /** @desc 请求服务器接口地址 */
41 | url?: string;
42 | /** @desc 请求方式,默认为 GET */
43 | method?: HttpMethod;
44 | /** @desc 请求基地址 */
45 | baseURL?: string;
46 | /** @desc 请求头信息,不能设置 Referer,App、H5 端会自动带上 cookie,且 H5 端不可手动修改 */
47 | header?: HttpRequestHeader;
48 | /** @desc 请求查询参数,自动拼接为查询字符串 */
49 | params?: HttpParams;
50 | /** @desc 请求体参数 */
51 | data?: HttpData;
52 | /** @desc 超时时间,单位 ms,默认为 60000,仅 H5 (HBuilderX 2.9.9+)、APP (HBuilderX 2.9.9+)、微信小程序 (2.10.0)、支付宝小程序支持 */
53 | timeout?: number;
54 | /** @desc 跨域请求时是否携带凭证 (cookies),默认为 false,仅 H5 (HBuilderX 2.6.15+) 支持 */
55 | withCredentials?: boolean;
56 | /** @desc 设置响应的数据类型,支付宝小程序不支持 */
57 | responseType?: HttpResponseType;
58 | /** @desc 全局自定义验证器 */
59 | validateStatus?: ((statusCode: number) => boolean) | null;
60 |
61 |
62 | /** params 参数自定义处理 */
63 | paramsSerializer?: (params: AnyObject) => string | void;
64 |
65 | /** @desc 默认为 json,如果设为 json,会尝试对返回的数据做一次 JSON.parse */
66 | dataType?: string;
67 | /** @desc DNS 解析时是否优先使用 ipv4,默认为 false,仅 App-Android (HBuilderX 2.8.0+) 支持 */
68 | firstIpv4?: boolean;
69 | /** @desc 是否验证 SSL 证书,默认为 true,仅 App-Android (HBuilderX 2.3.3+) 支持 */
70 | sslVerify?: boolean;
71 |
72 | /** @desc 开启 http2;微信小程序 */
73 | enableHttp2?: boolean;
74 |
75 | /** @desc 开启 quic;微信小程序 */
76 | enableQuic?: boolean;
77 | /** @desc 开启 cache;微信小程序、字节跳动小程序 2.31.0+ */
78 | enableCache?: boolean;
79 | /** @desc 开启 httpDNS;微信小程序 */
80 | enableHttpDNS?: boolean;
81 | /** @desc httpDNS 服务商;微信小程序 */
82 | httpDNSServiceId?: string;
83 | /** @desc 开启 transfer-encoding chunked;微信小程序 */
84 | enableChunked?: boolean;
85 | /** @desc wifi下使用移动网络发送请求;微信小程序 */
86 | forceCellularNetwork?: boolean;
87 | /** @desc 开启后可在headers中编辑cookie;支付宝小程序 10.2.33+ */
88 | enableCookie?: boolean;
89 | /** @desc 是否开启云加速;百度小程序 3.310.11+ */
90 | cloudCache?: boolean | object;
91 | /** @desc 控制当前请求是否延时至首屏内容渲染后发送;百度小程序 3.310.11+ */
92 | defer?: boolean;
93 |
94 | /** @desc 自定义参数 */
95 | custom?: HttpCustom;
96 |
97 | /** @desc 返回当前请求的 task 和 options,不要在这里修改 options */
98 | getTask?: (task: T, options: HttpRequestConfig) => void;
99 |
100 | /** @desc 需要上传的文件列表,使用 files 时,filePath 和 name 不生效,仅支持 App、H5 (2.6.15+) */
101 | files?: { name?: string; file?: File; uri: string; }[];
102 | /** @desc 文件类型,仅支付宝小程序支持且为必填项 */
103 | fileType?: HttpFileType;
104 | /** @desc 要上传的文件对象,仅 H5 (2.6.15+) 支持 */
105 | file?: File;
106 | /** @desc 要上传文件资源的路径,使用 files 时,filePath 和 name 不生效 */
107 | filePath?: string;
108 | /** @desc 文件对应的 key,开发者在服务器端通过这个 key 可以获取到文件二进制内容,使用 files 时,filePath 和 name 不生效 */
109 | name?: string;
110 | /** @desc 请求中其他额外的 form data */
111 | formData?: HttpFormData;
112 | }
113 |
114 | export interface HttpResponse {
115 | data: T;
116 | statusCode: number;
117 | header: HttpResponseHeader;
118 | config: HttpRequestConfig;
119 | cookies: string[];
120 | errMsg: string;
121 | rawData: any;
122 | }
123 |
124 | export interface HttpUploadResponse {
125 | data: T;
126 | statusCode: number;
127 | config: HttpRequestConfig;
128 | errMsg: string;
129 | rawData: any;
130 | }
131 |
132 | export interface HttpDownloadResponse extends HttpResponse {
133 | tempFilePath: string;
134 | apFilePath?: string;
135 | filePath?: string;
136 | fileContent?: string;
137 | }
138 |
139 | export interface HttpError {
140 | data?: T;
141 | statusCode?: number;
142 | header?: HttpResponseHeader;
143 | config: HttpRequestConfig;
144 | cookies?: string[];
145 | errMsg: string;
146 | }
147 |
148 | export interface HttpPromise extends Promise> {
149 | }
150 |
151 | export interface HttpInterceptorManager {
152 | use(onFulfilled?: (value: V) => V | Promise, onRejected?: (error: E) => T | Promise): void;
153 |
154 | eject(id: number): void;
155 | }
156 |
157 | export abstract class HttpRequestAbstract {
158 | constructor(config?: HttpRequestConfig);
159 |
160 | interceptors: {
161 | request: HttpInterceptorManager;
162 | response: HttpInterceptorManager;
163 | }
164 |
165 | request, D = HttpRequestTask>(config: HttpRequestConfig): Promise;
166 |
167 | get, D = HttpRequestTask>(url: string, config?: HttpRequestConfig): Promise;
168 |
169 | delete, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
170 |
171 | head, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
172 |
173 | options, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
174 |
175 | post, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
176 |
177 | put, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
178 |
179 | config: HttpRequestConfig;
180 |
181 | setConfig(onSend: (config: HttpRequestConfig) => HttpRequestConfig): void;
182 |
183 | connect, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
184 |
185 | trace, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig): Promise;
186 |
187 | upload, D = HttpUploadTask>(url: string, config?: HttpRequestConfig): Promise;
188 |
189 | download, D = HttpDownloadTask>(url: string, config?: HttpRequestConfig): Promise;
190 |
191 | middleware, D = HttpTask>(config: HttpRequestConfig): Promise;
192 | }
193 |
194 | declare class HttpRequest extends HttpRequestAbstract {
195 | }
196 |
197 | export default HttpRequest;
198 |
--------------------------------------------------------------------------------
/example/request-demo/utils/luch-request/index.d.ts:
--------------------------------------------------------------------------------
1 | export type HttpTask = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask;
2 |
3 | export type HttpRequestTask = UniApp.RequestTask;
4 |
5 | export type HttpUploadTask = UniApp.UploadTask;
6 |
7 | export type HttpDownloadTask = UniApp.DownloadTask;
8 |
9 | export type HttpMethod =
10 | "GET"
11 | | "POST"
12 | | "PUT"
13 | | "DELETE"
14 | | "CONNECT"
15 | | "HEAD"
16 | | "OPTIONS"
17 | | "TRACE"
18 | | "UPLOAD"
19 | | "DOWNLOAD";
20 |
21 | export type HttpRequestHeader = Record;
22 |
23 | export type HttpParams = Record;
24 |
25 | export type HttpData = Record;
26 |
27 | export type HttpResponseType = 'arraybuffer' | 'text';
28 |
29 | export type HttpCustom = Record;
30 |
31 | export type HttpFileType = 'image' | 'video' | 'audio';
32 |
33 | export type HttpFormData = Record;
34 |
35 | export type HttpResponseHeader = Record & {
36 | "set-cookie"?: string[]
37 | };
38 |
39 | export interface HttpRequestConfig {
40 | /** @desc 请求服务器接口地址 */
41 | url?: string;
42 | /** @desc 请求方式,默认为 GET */
43 | method?: HttpMethod;
44 | /** @desc 请求基地址 */
45 | baseURL?: string;
46 | /** @desc 请求头信息,不能设置 Referer,App、H5 端会自动带上 cookie,且 H5 端不可手动修改 */
47 | header?: HttpRequestHeader;
48 | /** @desc 请求查询参数,自动拼接为查询字符串 */
49 | params?: HttpParams;
50 | /** @desc 请求体参数 */
51 | data?: HttpData;
52 | /** @desc 超时时间,单位 ms,默认为 60000,仅 H5 (HBuilderX 2.9.9+)、APP (HBuilderX 2.9.9+)、微信小程序 (2.10.0)、支付宝小程序支持 */
53 | timeout?: number;
54 | /** @desc 跨域请求时是否携带凭证 (cookies),默认为 false,仅 H5 (HBuilderX 2.6.15+) 支持 */
55 | withCredentials?: boolean;
56 | /** @desc 设置响应的数据类型,支付宝小程序不支持 */
57 | responseType?: HttpResponseType;
58 | /** @desc 全局自定义验证器 */
59 | validateStatus?: ((statusCode: number) => boolean) | null;
60 |
61 |
62 | /** params 参数自定义处理 */
63 | paramsSerializer?: (params: AnyObject) => string | void;
64 |
65 | /** @desc 默认为 json,如果设为 json,会尝试对返回的数据做一次 JSON.parse */
66 | dataType?: string;
67 | /** @desc DNS 解析时是否优先使用 ipv4,默认为 false,仅 App-Android (HBuilderX 2.8.0+) 支持 */
68 | firstIpv4?: boolean;
69 | /** @desc 是否验证 SSL 证书,默认为 true,仅 App-Android (HBuilderX 2.3.3+) 支持 */
70 | sslVerify?: boolean;
71 |
72 | /** @desc 开启 http2;微信小程序 */
73 | enableHttp2?: boolean;
74 |
75 | /** @desc 开启 quic;微信小程序 */
76 | enableQuic?: boolean;
77 | /** @desc 开启 cache;微信小程序、字节跳动小程序 2.31.0+ */
78 | enableCache?: boolean;
79 | /** @desc 开启 httpDNS;微信小程序 */
80 | enableHttpDNS?: boolean;
81 | /** @desc httpDNS 服务商;微信小程序 */
82 | httpDNSServiceId?: string;
83 | /** @desc 开启 transfer-encoding chunked;微信小程序 */
84 | enableChunked?: boolean;
85 | /** @desc wifi下使用移动网络发送请求;微信小程序 */
86 | forceCellularNetwork?: boolean;
87 | /** @desc 开启后可在headers中编辑cookie;支付宝小程序 10.2.33+ */
88 | enableCookie?: boolean;
89 | /** @desc 是否开启云加速;百度小程序 3.310.11+ */
90 | cloudCache?: boolean | object;
91 | /** @desc 控制当前请求是否延时至首屏内容渲染后发送;百度小程序 3.310.11+ */
92 | defer?: boolean;
93 |
94 | /** @desc 自定义参数 */
95 | custom?: HttpCustom;
96 |
97 | /** @desc 返回当前请求的 task 和 options,不要在这里修改 options */
98 | getTask?: (task: T, options: HttpRequestConfig) => void;
99 |
100 | /** @desc 需要上传的文件列表,使用 files 时,filePath 和 name 不生效,仅支持 App、H5 (2.6.15+) */
101 | files?: { name?: string; file?: File; uri: string; }[];
102 | /** @desc 文件类型,仅支付宝小程序支持且为必填项 */
103 | fileType?: HttpFileType;
104 | /** @desc 要上传的文件对象,仅 H5 (2.6.15+) 支持 */
105 | file?: File;
106 | /** @desc 要上传文件资源的路径,使用 files 时,filePath 和 name 不生效 */
107 | filePath?: string;
108 | /** @desc 文件对应的 key,开发者在服务器端通过这个 key 可以获取到文件二进制内容,使用 files 时,filePath 和 name 不生效 */
109 | name?: string;
110 | /** @desc 请求中其他额外的 form data */
111 | formData?: HttpFormData;
112 | }
113 |
114 | export interface HttpResponse {
115 | data: T;
116 | statusCode: number;
117 | header: HttpResponseHeader;
118 | config: HttpRequestConfig;
119 | cookies: string[];
120 | errMsg: string;
121 | rawData: any;
122 | }
123 |
124 | export interface HttpUploadResponse {
125 | data: T;
126 | statusCode: number;
127 | config: HttpRequestConfig;
128 | errMsg: string;
129 | rawData: any;
130 | }
131 |
132 | export interface HttpDownloadResponse extends HttpResponse {
133 | tempFilePath: string;
134 | apFilePath?: string;
135 | filePath?: string;
136 | fileContent?: string;
137 | }
138 |
139 | export interface HttpError {
140 | data?: T;
141 | statusCode?: number;
142 | header?: HttpResponseHeader;
143 | config: HttpRequestConfig;
144 | cookies?: string[];
145 | errMsg: string;
146 | }
147 |
148 | export interface HttpPromise extends Promise> {
149 | }
150 |
151 | export interface HttpInterceptorManager {
152 | use(onFulfilled?: (value: V) => V | Promise, onRejected?: (error: E) => T | Promise): void;
153 |
154 | eject(id: number): void;
155 | }
156 |
157 | export abstract class HttpRequestAbstract {
158 | constructor(config?: HttpRequestConfig);
159 |
160 | interceptors: {
161 | request: HttpInterceptorManager;
162 | response: HttpInterceptorManager;
163 | }
164 |
165 | request