From 796424a0d929a9cc2793d0e9d5ea0eeabd9f72c8 Mon Sep 17 00:00:00 2001 From: "Thomas.Lin" Date: Sat, 16 Nov 2019 10:35:17 +0800 Subject: [PATCH 1/2] Create README_CN.md add Chinese README_CN.md --- README_CN.md | 733 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 733 insertions(+) create mode 100644 README_CN.md diff --git a/README_CN.md b/README_CN.md new file mode 100644 index 0000000000..5d8d889f77 --- /dev/null +++ b/README_CN.md @@ -0,0 +1,733 @@ +# axios + +[![npm version](https://img.shields.io/npm/v/axios.svg?style=flat-square)](https://www.npmjs.org/package/axios) +[![build status](https://img.shields.io/travis/axios/axios.svg?style=flat-square)](https://travis-ci.org/axios/axios) +[![code coverage](https://img.shields.io/coveralls/mzabriskie/axios.svg?style=flat-square)](https://coveralls.io/r/mzabriskie/axios) +[![install size](https://packagephobia.now.sh/badge?p=axios)](https://packagephobia.now.sh/result?p=axios) +[![npm downloads](https://img.shields.io/npm/dm/axios.svg?style=flat-square)](http://npm-stat.com/charts.html?package=axios) +[![gitter chat](https://img.shields.io/gitter/room/mzabriskie/axios.svg?style=flat-square)](https://gitter.im/mzabriskie/axios) +[![code helpers](https://www.codetriage.com/axios/axios/badges/users.svg)](https://www.codetriage.com/axios/axios) + +基于Promise的浏览器和node.js HTTP客户端 +## 特点 + +- 发送[XMLHttpRequests](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) 请求 +- 在node.js中发送[http](http://nodejs.org/api/http.html) 请求 +- 支持[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API +- 拦截request和response +- 转换request和response数据 +- 取消请求 +- JSON数据的自动转换 +- 在客户端防止[XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) + +## 浏览器支持 + +| ![Chrome](axios.assets/chrome_48x48.png) | ![Firefox](axios.assets/firefox_48x48.png) | ![Safari](axios.assets/safari_48x48.png) | ![Opera](axios.assets/opera_48x48.png) | ![Edge](axios.assets/edge_48x48.png) | ![IE](axios.assets/internet-explorer_9-11_48x48.png) | | +| ---------------------------------------- | ------------------------------------------ | ---------------------------------------- | -------------------------------------- | ------------------------------------ | ---------------------------------------------------- | ---- | +| Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | 11 ✔ | | + +[![Browser Matrix](https://saucelabs.com/open_sauce/build_matrix/axios.svg)](https://saucelabs.com/u/axios) + +## 安装 + +使用 npm: + +```bash +$ npm install axios +``` + +使用 bower: + +```bash +$ bower install axios +``` + +使用 yarn: + +```bash +$ yarn add axios +``` + +使用 cdn: + +```html + +``` + +## 例子 + +### 注意: CommonJS 的使用 + +为了能够获得TypeScript编码的智能感知和自动补全,使用CommonJS imports的时候,用以下的方式使用`require()` + +```js +const axios = require('axios').default; + +// axios. 现在可以提供自动补全和参数输入 +``` + +执行一个 `GET` 请求 + +```js +const axios = require('axios'); + +// Make a request for a user with a given ID +axios.get('/user?ID=12345') + .then(function (response) { + // handle success + console.log(response); + }) + .catch(function (error) { + // handle error + console.log(error); + }) + .finally(function () { + // always executed + }); + +// Optionally the request above could also be done as +axios.get('/user', { + params: { + ID: 12345 + } + }) + .then(function (response) { + console.log(response); + }) + .catch(function (error) { + console.log(error); + }) + .finally(function () { + // always executed + }); + +// Want to use async/await? Add the `async` keyword to your outer function/method. +async function getUser() { + try { + const response = await axios.get('/user?ID=12345'); + console.log(response); + } catch (error) { + console.error(error); + } +} +``` + +> **NOTE:** `async/await` is part of ECMAScript 2017 and is not supported in Internet +> Explorer and older browsers, so use with caution. + +执行一个 `POST` 请求 + +```js +axios.post('/user', { + firstName: 'Fred', + lastName: 'Flintstone' + }) + .then(function (response) { + console.log(response); + }) + .catch(function (error) { + console.log(error); + }); +``` + +执行多个并发请求 + +```js +function getUserAccount() { + return axios.get('/user/12345'); +} + +function getUserPermissions() { + return axios.get('/user/12345/permissions'); +} + +axios.all([getUserAccount(), getUserPermissions()]) + .then(axios.spread(function (acct, perms) { + // Both requests are now complete + })); +``` + +## axios API + +同样的道理,你可以通过传递相关的配置来发送请求`axios`. + +##### axios(config) + +```js +// Send a POST request +axios({ + method: 'post', + url: '/user/12345', + data: { + firstName: 'Fred', + lastName: 'Flintstone' + } +}); +``` + +```js +// GET request for remote image +axios({ + method: 'get', + url: 'http://bit.ly/2mTM3nY', + responseType: 'stream' +}) + .then(function (response) { + response.data.pipe(fs.createWriteStream('ada_lovelace.jpg')) + }); +``` + +##### axios(url[, config]) + +```js +// Send a GET request (default method) +axios('/user/12345'); +``` + +### Request 方法的别称 + +所有支持的方法都有通俗易懂的别称 + +##### axios.request(config) + +##### axios.get(url[, config]) + +##### axios.delete(url[, config]) + +##### axios.head(url[, config]) + +##### axios.options(url[, config]) + +##### axios.post(url[, data[, config]]) + +##### axios.put(url[, data[, config]]) + +##### axios.patch(url[, data[, config]]) + +###### 注意 + +当你使用方法别称的时候, `url`, `method`, 和 `data` 等属性都不需要在配置中指定。 + +### 并发 + +解决并发请求的帮助函数 + +##### axios.all(iterable) + +##### axios.spread(callback) + +### Creating an instance + +你可以使用新的axios的实例创建一个自定义的配置 + +##### axios.create([config]) + +```js +const instance = axios.create({ + baseURL: 'https://some-domain.com/api/', + timeout: 1000, + headers: {'X-Custom-Header': 'foobar'} +}); +``` + +### 实例的方法 + +下面是可以应用到的实例方法。这些指定的配置都可以被合并到实例的配置中。 + +##### axios#request(config) + +##### axios#get(url[, config]) + +##### axios#delete(url[, config]) + +##### axios#head(url[, config]) + +##### axios#options(url[, config]) + +##### axios#post(url[, data[, config]]) + +##### axios#put(url[, data[, config]]) + +##### axios#patch(url[, data[, config]]) + +##### axios#getUri([config]) + +## 请求配置 + +这些是用于发送请求的可用配置项。只有 `url`是必须的。如果 `method`没有被指定的话,Requests默认是`GET`. + +```js +{ + // `url` is the server URL that will be used for the request + url: '/user', + + // `method` is the request method to be used when making the request + method: 'get', // default + + // `baseURL` will be prepended to `url` unless `url` is absolute. + // It can be convenient to set `baseURL` for an instance of axios to pass relative URLs + // to methods of that instance. + baseURL: 'https://some-domain.com/api/', + + // `transformRequest` allows changes to the request data before it is sent to the server + // This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE' + // The last function in the array must return a string or an instance of Buffer, ArrayBuffer, + // FormData or Stream + // You may modify the headers object. + transformRequest: [function (data, headers) { + // Do whatever you want to transform the data + + return data; + }], + + // `transformResponse` allows changes to the response data to be made before + // it is passed to then/catch + transformResponse: [function (data) { + // Do whatever you want to transform the data + + return data; + }], + + // `headers` are custom headers to be sent + headers: {'X-Requested-With': 'XMLHttpRequest'}, + + // `params` are the URL parameters to be sent with the request + // Must be a plain object or a URLSearchParams object + params: { + ID: 12345 + }, + + // `paramsSerializer` is an optional function in charge of serializing `params` + // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/) + paramsSerializer: function (params) { + return Qs.stringify(params, {arrayFormat: 'brackets'}) + }, + + // `data` is the data to be sent as the request body + // Only applicable for request methods 'PUT', 'POST', and 'PATCH' + // When no `transformRequest` is set, must be of one of the following types: + // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams + // - Browser only: FormData, File, Blob + // - Node only: Stream, Buffer + data: { + firstName: 'Fred' + }, + + // syntax alternative to send data into the body + // method post + // only the value is sent, not the key + data: 'Country=Brasil&City=Belo Horizonte', + + // `timeout` specifies the number of milliseconds before the request times out. + // If the request takes longer than `timeout`, the request will be aborted. + timeout: 1000, // default is `0` (no timeout) + + // `withCredentials` indicates whether or not cross-site Access-Control requests + // should be made using credentials + withCredentials: false, // default + + // `adapter` allows custom handling of requests which makes testing easier. + // Return a promise and supply a valid response (see lib/adapters/README.md). + adapter: function (config) { + /* ... */ + }, + + // `auth` indicates that HTTP Basic auth should be used, and supplies credentials. + // This will set an `Authorization` header, overwriting any existing + // `Authorization` custom headers you have set using `headers`. + // Please note that only HTTP Basic auth is configurable through this parameter. + // For Bearer tokens and such, use `Authorization` custom headers instead. + auth: { + username: 'janedoe', + password: 's00pers3cret' + }, + + // `responseType` indicates the type of data that the server will respond with + // options are: 'arraybuffer', 'document', 'json', 'text', 'stream' + // browser only: 'blob' + responseType: 'json', // default + + // `responseEncoding` indicates encoding to use for decoding responses + // Note: Ignored for `responseType` of 'stream' or client-side requests + responseEncoding: 'utf8', // default + + // `xsrfCookieName` is the name of the cookie to use as a value for xsrf token + xsrfCookieName: 'XSRF-TOKEN', // default + + // `xsrfHeaderName` is the name of the http header that carries the xsrf token value + xsrfHeaderName: 'X-XSRF-TOKEN', // default + + // `onUploadProgress` allows handling of progress events for uploads + onUploadProgress: function (progressEvent) { + // Do whatever you want with the native progress event + }, + + // `onDownloadProgress` allows handling of progress events for downloads + onDownloadProgress: function (progressEvent) { + // Do whatever you want with the native progress event + }, + + // `maxContentLength` defines the max size of the http response content in bytes allowed + maxContentLength: 2000, + + // `validateStatus` defines whether to resolve or reject the promise for a given + // HTTP response status code. If `validateStatus` returns `true` (or is set to `null` + // or `undefined`), the promise will be resolved; otherwise, the promise will be + // rejected. + validateStatus: function (status) { + return status >= 200 && status < 300; // default + }, + + // `maxRedirects` defines the maximum number of redirects to follow in node.js. + // If set to 0, no redirects will be followed. + maxRedirects: 5, // default + + // `socketPath` defines a UNIX Socket to be used in node.js. + // e.g. '/var/run/docker.sock' to send requests to the docker daemon. + // Only either `socketPath` or `proxy` can be specified. + // If both are specified, `socketPath` is used. + socketPath: null, // default + + // `httpAgent` and `httpsAgent` define a custom agent to be used when performing http + // and https requests, respectively, in node.js. This allows options to be added like + // `keepAlive` that are not enabled by default. + httpAgent: new http.Agent({ keepAlive: true }), + httpsAgent: new https.Agent({ keepAlive: true }), + + // 'proxy' defines the hostname and port of the proxy server. + // You can also define your proxy using the conventional `http_proxy` and + // `https_proxy` environment variables. If you are using environment variables + // for your proxy configuration, you can also define a `no_proxy` environment + // variable as a comma-separated list of domains that should not be proxied. + // Use `false` to disable proxies, ignoring environment variables. + // `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and + // supplies credentials. + // This will set an `Proxy-Authorization` header, overwriting any existing + // `Proxy-Authorization` custom headers you have set using `headers`. + proxy: { + host: '127.0.0.1', + port: 9000, + auth: { + username: 'mikeymike', + password: 'rapunz3l' + } + }, + + // `cancelToken` specifies a cancel token that can be used to cancel the request + // (see Cancellation section below for details) + cancelToken: new CancelToken(function (cancel) { + }) +} +``` + +## 响应的 配置 + +一个请求的响应包含了以下的信息。 + +```js +{ + // `data` is the response that was provided by the server + data: {}, + + // `status` is the HTTP status code from the server response + status: 200, + + // `statusText` is the HTTP status message from the server response + statusText: 'OK', + + // `headers` the headers that the server responded with + // All header names are lower cased + headers: {}, + + // `config` is the config that was provided to `axios` for the request + config: {}, + + // `request` is the request that generated this response + // It is the last ClientRequest instance in node.js (in redirects) + // and an XMLHttpRequest instance in the browser + request: {} +} +``` + +当使用`then`的时候,你会收到以下的响应: + +```js +axios.get('/user/12345') + .then(function (response) { + console.log(response.data); + console.log(response.status); + console.log(response.statusText); + console.log(response.headers); + console.log(response.config); + }); +``` + + +当使用`catch`或者传递一个[rejection callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then)作为`then`的第二个参数,将可以在响应中使用`error`对象,这一部分在[Handling Errors](#handling-errors)中有说到。 + +## 默认配置 + +你指定的默认配置将会被应用到每个请求中 + +### 全局的axios配置 + +```js +axios.defaults.baseURL = 'https://api.example.com'; +axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; +axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; +``` + +### 自定义的默认实例 + +```js +// Set config defaults when creating the instance +const instance = axios.create({ + baseURL: 'https://api.example.com' +}); + +// Alter defaults after instance has been created +instance.defaults.headers.common['Authorization'] = AUTH_TOKEN; +``` + +### 配置的优先顺序 + + +配置将会以以下的优先顺序被合并。默认配置在[lib/defaults.js](https://github.com/axios/axios/blob/master/lib/defaults.js#L28)里面可以找到。然后是实例的 `defaults`属性,之后就是请求的`config`参数。后者将会比前者优先权更高。下面是一个例子。 + +```js +// Create an instance using the config defaults provided by the library +// At this point the timeout config value is `0` as is the default for the library +const instance = axios.create(); + +// Override timeout default for the library +// Now all requests using this instance will wait 2.5 seconds before timing out +instance.defaults.timeout = 2500; + +// Override timeout for this request as it's known to take a long time +instance.get('/longRequest', { + timeout: 5000 +}); +``` + +## Interceptors + +你可以在请求或者响应被拦截前使用 `then` 或者`catch` + +```js +// Add a request interceptor +axios.interceptors.request.use(function (config) { + // Do something before request is sent + return config; + }, function (error) { + // Do something with request error + return Promise.reject(error); + }); + +// Add a response interceptor +axios.interceptors.response.use(function (response) { + // Any status code that lie within the range of 2xx cause this function to trigger + // Do something with response data + return response; + }, function (error) { + // Any status codes that falls outside the range of 2xx cause this function to trigger + // Do something with response error + return Promise.reject(error); + }); +``` + +如果你想移除一个拦截器你可以 + +```js +const myInterceptor = axios.interceptors.request.use(function () {/*...*/}); +axios.interceptors.request.eject(myInterceptor); +``` + +你可以添加一个拦截器到一个自定义的axios实例中。 + +```js +const instance = axios.create(); +instance.interceptors.request.use(function () {/*...*/}); +``` + +## 处理 Errors + +```js +axios.get('/user/12345') + .catch(function (error) { + if (error.response) { + // The request was made and the server responded with a status code + // that falls out of the range of 2xx + console.log(error.response.data); + console.log(error.response.status); + console.log(error.response.headers); + } else if (error.request) { + // The request was made but no response was received + // `error.request` is an instance of XMLHttpRequest in the browser and an instance of + // http.ClientRequest in node.js + console.log(error.request); + } else { + // Something happened in setting up the request that triggered an Error + console.log('Error', error.message); + } + console.log(error.config); + }); +``` + +使用`validateStatus`配置选项,你可以定义应该抛出错误的HTTP代码。 + +```js +axios.get('/user/12345', { + validateStatus: function (status) { + return status < 500; // Reject only if the status code is greater than or equal to 500 + } +}) +``` + +使用`toJSON`你可以获取更多关于HTTP错误的信息 + +```js +axios.get('/user/12345') + .catch(function (error) { + console.log(error.toJSON()); + }); +``` + +## 取消 + +你可以使用*cancel token*取消一个请求 + +> axios的请求token API是基于 [cancelable promises proposal](https://github.com/tc39/proposal-cancelable-promises). + +你可以使用 `CancelToken.source` 工厂类创建一个cancel token,如下所示: + +```js +const CancelToken = axios.CancelToken; +const source = CancelToken.source(); + +axios.get('/user/12345', { + cancelToken: source.token +}).catch(function (thrown) { + if (axios.isCancel(thrown)) { + console.log('Request canceled', thrown.message); + } else { + // handle error + } +}); + +axios.post('/user/12345', { + name: 'new name' +}, { + cancelToken: source.token +}) + +// cancel the request (the message parameter is optional) +source.cancel('Operation canceled by the user.'); +``` + +你也可以通过向`CancelToken`构造函数传递一个执行方法的方式创建一个cancel token: + +```js +const CancelToken = axios.CancelToken; +let cancel; + +axios.get('/user/12345', { + cancelToken: new CancelToken(function executor(c) { + // An executor function receives a cancel function as a parameter + cancel = c; + }) +}); + +// cancel the request +cancel(); +``` + +> 注意: 你可以使用同样的cancel token取消几个请求 + +## 使用 application/x-www-form-urlencoded 格式 + +默认情况下,axios 将JavaScript对象序列成`JSON`.为了能够发送`application/x-www-form-urlencoded` 的数据格式,你可以使用以下的选项. + +### 浏览器 + +在浏览器中, 你可以使用 [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) 如下的API: + +```js +const params = new URLSearchParams(); +params.append('param1', 'value1'); +params.append('param2', 'value2'); +axios.post('/foo', params); +``` + +> 注意到 `URLSearchParams`并不支持所有的浏览器(见[caniuse.com](http://www.caniuse.com/#feat=urlsearchparams) ),但是这里有一个可供使用的 [polyfill](https://github.com/WebReflection/url-search-params) 版本(注意到要确保可以polyfill全局的变量) + +可选的,你可以使用 [`qs`](https://github.com/ljharb/qs) 库来编码数据: + +```js +const qs = require('qs'); +axios.post('/foo', qs.stringify({ 'bar': 123 })); +``` + +或者使用ES6的方式 + +```js +import qs from 'qs'; +const data = { 'bar': 123 }; +const options = { + method: 'POST', + headers: { 'content-type': 'application/x-www-form-urlencoded' }, + data: qs.stringify(data), + url, +}; +axios(options); +``` + +### Node.js + + 在node.js中,你可以使用[`querystring`](https://nodejs.org/api/querystring.html)以下的模块: + +```js +const querystring = require('querystring'); +axios.post('http://something.com/', querystring.stringify({ foo: 'bar' })); +``` + +同样你也可以使用 [`qs`](https://github.com/ljharb/qs) 库. + +###### 注意 + +如果你想要字符串化嵌套的对象,那么 `qs`库是我们推荐的,当然`querystring`方法同样也有一些用例上的问题 (https://github.com/nodejs/node-v0.x-archive/issues/1665) + +## Semver + +直到axios到达`1.0`发布版本,重大的改变将会被发布,同样也会有一些小的版本。例如`0.5.1`和 `0.5.4` 将会有同样的API,但是`0.6.0`将会有重大的改变。 + +## Promises + +axios depends on a native ES6 Promise implementation to be [supported](http://caniuse.com/promises). +If your environment doesn't support ES6 Promises, you can. + +axios取决于一个将要被实现的原生ES6 Promise的实现(http://caniuse.com/promises),如果你的环境不支持ES6的原生Promises,你可以 [polyfill](https://github.com/jakearchibald/es6-promise). + +## TypeScript + +axios 包含了 [TypeScript](http://typescriptlang.org) 定义. + +```typescript +import axios from 'axios'; +axios.get('/user?ID=12345'); +``` + +## 资源 + +* [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md) +* [Upgrade Guide](https://github.com/axios/axios/blob/master/UPGRADE_GUIDE.md) +* [Ecosystem](https://github.com/axios/axios/blob/master/ECOSYSTEM.md) +* [Contributing Guide](https://github.com/axios/axios/blob/master/CONTRIBUTING.md) +* [Code of Conduct](https://github.com/axios/axios/blob/master/CODE_OF_CONDUCT.md) + +## Credits + +axios is heavily inspired by the [$http service](https://docs.angularjs.org/api/ng/service/$http) provided in [Angular](https://angularjs.org/). Ultimately axios is an effort to provide a standalone `$http`-like service for use outside of Angular. + +## License + +[MIT](LICENSE) From 57db17f7bcfffbc61f6f5efdf3fac0e9c360887a Mon Sep 17 00:00:00 2001 From: "thomas.lin" Date: Tue, 19 Nov 2019 08:35:26 +0800 Subject: [PATCH 2/2] add native allSettled method for axios from Promise --- lib/axios.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/axios.js b/lib/axios.js index 8142437983..46ca27a0ef 100644 --- a/lib/axios.js +++ b/lib/axios.js @@ -41,10 +41,15 @@ axios.Cancel = require('./cancel/Cancel'); axios.CancelToken = require('./cancel/CancelToken'); axios.isCancel = require('./cancel/isCancel'); -// Expose all/spread +// Expose all/spread/allSettled axios.all = function all(promises) { return Promise.all(promises); }; + +axios.allSettled = function allSettled(promises){ + return Promise.allSettled(promises); +}; + axios.spread = require('./helpers/spread'); module.exports = axios;