Skip to content

Commit

Permalink
Feat: add abort request polyfill and update types (#148)
Browse files Browse the repository at this point in the history
* feat: add AbortController polyfill

* doc: update cases; update types
  • Loading branch information
chenjsh36 authored May 22, 2020
1 parent 4522b07 commit 6a424cf
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 45 deletions.
49 changes: 28 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,34 @@ clientB.interceptors.request.use(

## Cancel request

### Use AbortController

Base on [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) that allows you to abort one or more Web requests as and when desired.

```javascript
import Request, { AbortController } from 'umi-request';

const controller = new AbortController(); // create a controller
const { signal } = controller; // grab a reference to its associated AbortSignal object using the AbortController.signal property

signal.addEventListener('abort', () => {
console.log('aborted!');
});

Request('/api/response_after_1_sec', {
signal, // pass in the AbortSignal as an option inside the request's options object (see {signal}, below). This associates the signal and controller with the fetch request and allows us to abort it by calling AbortController.abort(),
});

// 取消请求
setTimeout(() => {
controller.abort(); // Aborts a DOM request before it has completed. This is able to abort fetch requests, consumption of any response Body, and streams.
}, 100);
```

### Use Cancel Token

> Cancel Token still work, but we don’t recommend using them in the new code.
1. You can cancel a request using a cancel token.

```javascript
Expand Down Expand Up @@ -770,27 +798,6 @@ Request.get('/api/cancel', {
cancel();
```

3. create AbortCOntroller cancel

```javascript
import Request, { AbortController } from 'umi-request';

const controller = new AbortController();
const { signal } = controller;

signal.addEventListener('abort', () => {
console.log('aborted!');
});

Request('http://127.0.0.1:3009/', {
signal,
});
// 取消请求
setTimeout(() => {
controller.abort();
}, 1000);
```

## Cases

### How to get Response Headers
Expand Down
53 changes: 32 additions & 21 deletions README_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -715,11 +715,41 @@ clientB.interceptors.request.use(
);
```

## 取消请求
## 中止请求

### 通过 AbortController 来中止请求

基于 [AbortController](https://developer.mozilla.org/zh-CN/docs/Web/API/FetchController) 方案来中止一个或多个DOM请求

```javascript
import Request, { AbortController } from 'umi-request';

const controller = new AbortController(); // 创建一个控制器
const { signal } = controller; // 返回一个 AbortSignal 对象实例,它可以用来 with/abort 一个 DOM 请求。

signal.addEventListener('abort', () => {
console.log('aborted!');
});

Request('/api/response_after_1_sec', {
signal, // 这将信号和控制器与获取请求相关联然后允许我们通过调用 AbortController.abort() 中止请求
});

// 取消请求
setTimeout(() => {
controller.abort(); // 中止一个尚未完成的DOM请求。这能够中止 fetch 请求,任何响应Body的消费者和流。
}, 100);
```

### 使用cancel token 方案来中止请求

> Cancel Token 将逐步退出历史舞台,推荐使用 AbortController 来实现请求中止。

你可以通过 **cancel token** 来取消一个请求

> cancel token API 是基于已被撤销的 [cancelable-promises 方案](https://github.com/tc39/proposal-cancelable-promises)
> cancel token API 是基于已被撤销的 [cancelable-promises 方案](https://github.com/tc39/proposal-cancelable-promises)

1. 你可以通过 **CancelToken.source** 来创建一个 cancel token,如下所示:

Expand Down Expand Up @@ -770,26 +800,7 @@ Request.get('/api/cancel', {
cancel();
```

3. 通过 AbortCOntroller 取消

```javascript
import Request, { AbortController } from 'umi-request';

const controller = new AbortController();
const { signal } = controller;

signal.addEventListener('abort', () => {
console.log('aborted!');
});

Request('http://127.0.0.1:3009/', {
signal,
});
// 取消请求
setTimeout(() => {
controller.abort();
}, 1000);
```

## 案例

Expand Down
21 changes: 20 additions & 1 deletion src/cancel/abortControllerCancel.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
import AbortController from 'abort-controller';
import { AbortController as AcAbortController, AbortSignal as AcAbortSignal } from 'abort-controller';

let AbortController = undefined;
let AbortSignal = undefined;

const g =
typeof self !== 'undefined'
? self
: typeof window !== 'undefined'
? window
: typeof global !== 'undefined'
? global
: /* otherwise */ undefined;

if (g) {
AbortController = typeof g.AbortController !== 'undefined' ? g.AbortController : AcAbortController;
AbortSignal = typeof g.AbortSignal !== 'undefined' ? g.AbortSignal : AcAbortSignal;
}

export default AbortController;

export { AbortController, AbortSignal };
5 changes: 3 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import request, { extend, fetch } from './request';
import Onion from './onion';
import { RequestError, ResponseError } from './utils';
import AbortController from './cancel/abortControllerCancel';
import { AbortController, AbortSignal } from './cancel/abortControllerCancel';

export { extend, RequestError, ResponseError, Onion, fetch, AbortController, AbortSignal };

export { extend, RequestError, ResponseError, Onion, fetch, AbortController };
export default request;
41 changes: 41 additions & 0 deletions test/cancel/abortControllerCancel.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import createTestServer from 'create-test-server';
import request, { AbortController } from '../../src/index';

const writeData = (data, res) => {
res.setHeader('access-control-allow-origin', '*');
res.send(data);
};

describe('test abortController', () => {
let server;

beforeAll(async () => {
server = await createTestServer();
});

afterAll(() => {
server.close();
});

const prefix = api => `${server.url}${api}`;

jest.useFakeTimers();

it('test request abort', () => {
expect.assertions(2);
server.get('/test/abort1', (req, res) => {
setTimeout(() => {
writeData(req.query, res);
}, 2000);
});

const controller = new AbortController();
const { signal } = controller;
setTimeout(() => {
controller.abort();
}, 500);
expect(signal.aborted).toBe(false);
jest.runAllTimers();
expect(signal.aborted).toBe(true);
});
});
4 changes: 4 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface RequestOptionsInit extends RequestInit {
getResponse?: boolean;
validateCache?: (url: string, options: RequestOptionsInit) => boolean;
__umiRequestCoreType__?: string;
[key: string]: any;
}

export interface RequestOptionsWithoutResponse extends RequestOptionsInit {
Expand Down Expand Up @@ -163,4 +164,7 @@ declare var request: RequestMethod;

export declare var fetch: RequestMethod;

export declare var AbortController: { prototype: AbortController; new (): AbortController };
export declare var AbortSignal: { prototype: AbortSignal; new (): AbortSignal };

export default request;

0 comments on commit 6a424cf

Please sign in to comment.