mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 22:36:31 +08:00
Add promise-like interface (#10470)
* Add promise-like interface * Keep hide interface * Shorten * Test Promise * Update document * Update demo: 2.5 second is insignificant with the default 3s hiding * Update demo: then interface * Fix line break * Chainable * Thenable demo * Thenable test * Fix tsc error * Fix tsc error * Better document * Revert change in loading.md * Change snapshot
This commit is contained in:
parent
f3869270ae
commit
c2519e776b
@ -61,3 +61,14 @@ exports[`renders ./components/message/demo/other.md correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/message/demo/thenable.md correctly 1`] = `
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Display a sequence of message
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
@ -85,6 +85,17 @@ describe('message', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should be called like promise', () => {
|
||||
jest.useRealTimers();
|
||||
const defaultDuration = 3;
|
||||
const now = Date.now();
|
||||
message.info('whatever').then(() => {
|
||||
// calculate the approximately duration value
|
||||
const aboutDuration = parseInt((Date.now() - now) / 1000, 10);
|
||||
expect(aboutDuration).toBe(defaultDuration);
|
||||
});
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/8201
|
||||
it('should hide message correctly', () => {
|
||||
let hide;
|
||||
|
28
components/message/demo/thenable.md
Normal file
28
components/message/demo/thenable.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
order: 5
|
||||
title:
|
||||
zh-CN: Promise 接口
|
||||
en-US: Promise interface
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以通过 then 接口在关闭后运行 callback 。以上用例将在每个 message 将要结束时通过 then 显示新的 message 。
|
||||
|
||||
## en-US
|
||||
`message` provides promise interface for `onClose`. The above example will display a new message when old message is about to finish.
|
||||
|
||||
````jsx
|
||||
import { message, Button } from 'antd';
|
||||
|
||||
const success = () => {
|
||||
message.loading('Action in progress..', 2.5)
|
||||
.then(() => message.success('Loading finished', 2.5))
|
||||
.then(() => message.info('Loading finished is finished', 2.5));
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<Button onClick={success}>Display a sequence of message</Button>
|
||||
, mountNode);
|
||||
````
|
||||
|
@ -34,6 +34,12 @@ Methods for global configuration and destruction are also provided:
|
||||
- `message.config(options)`
|
||||
- `message.destroy()`
|
||||
|
||||
`afterClose` can be called in then-able interface:
|
||||
- `message[level](content, [duration]).then(afterClose)`
|
||||
- `message[level](content, [duration], onClose).then(afterClose)`
|
||||
|
||||
where `level` refers one static methods of `message`. The result of `then` method will be a Promise.
|
||||
|
||||
### message.config
|
||||
|
||||
```js
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* global Promise */
|
||||
import * as React from 'react';
|
||||
import Notification from 'rc-notification';
|
||||
import Icon from '../icon';
|
||||
@ -34,12 +35,22 @@ function getMessageInstance(callback: (i: any) => void) {
|
||||
|
||||
type NoticeType = 'info' | 'success' | 'error' | 'warning' | 'loading';
|
||||
|
||||
export interface ThenableArgument {
|
||||
(_: any): any;
|
||||
}
|
||||
|
||||
export interface MessageType {
|
||||
(): void;
|
||||
then: (fill: ThenableArgument, reject: ThenableArgument) => Promise<any>;
|
||||
promise: Promise<any>;
|
||||
}
|
||||
|
||||
function notice(
|
||||
content: React.ReactNode,
|
||||
duration: (() => void) | number = defaultDuration,
|
||||
type: NoticeType,
|
||||
onClose?: () => void,
|
||||
) {
|
||||
): MessageType {
|
||||
const iconType = ({
|
||||
info: 'info-circle',
|
||||
success: 'check-circle',
|
||||
@ -54,25 +65,36 @@ function notice(
|
||||
}
|
||||
|
||||
const target = key++;
|
||||
getMessageInstance((instance) => {
|
||||
instance.notice({
|
||||
key: target,
|
||||
duration,
|
||||
style: {},
|
||||
content: (
|
||||
<div className={`${prefixCls}-custom-content ${prefixCls}-${type}`}>
|
||||
<Icon type={iconType} />
|
||||
<span>{content}</span>
|
||||
</div>
|
||||
),
|
||||
onClose,
|
||||
const closePromise = new Promise((resolve) => {
|
||||
const callback = () => {
|
||||
if (typeof onClose === 'function') {
|
||||
onClose();
|
||||
}
|
||||
return resolve(true);
|
||||
};
|
||||
getMessageInstance((instance) => {
|
||||
instance.notice({
|
||||
key: target,
|
||||
duration,
|
||||
style: {},
|
||||
content: (
|
||||
<div className={`${prefixCls}-custom-content ${prefixCls}-${type}`}>
|
||||
<Icon type={iconType} />
|
||||
<span>{content}</span>
|
||||
</div>
|
||||
),
|
||||
onClose: callback,
|
||||
});
|
||||
});
|
||||
});
|
||||
return () => {
|
||||
const result: any = () => {
|
||||
if (messageInstance) {
|
||||
messageInstance.removeNotice(target);
|
||||
}
|
||||
};
|
||||
result.then = (filled: ThenableArgument, rejected: ThenableArgument) => closePromise.then(filled, rejected);
|
||||
result.promise = closePromise;
|
||||
return result;
|
||||
}
|
||||
|
||||
type ConfigContent = React.ReactNode | string;
|
||||
|
@ -35,6 +35,13 @@ title: Message
|
||||
- `message.config(options)`
|
||||
- `message.destroy()`
|
||||
|
||||
组件同时提供 promise 接口
|
||||
|
||||
- `message[level](content, [duration]).then(afterClose)`
|
||||
- `message[level](content, [duration], onClose).then(afterClose)`
|
||||
|
||||
其中`message[level]` 是组件已经提供的静态方法。`then` 接口返回值是 Promise 。
|
||||
|
||||
### message.config
|
||||
|
||||
```js
|
||||
|
Loading…
Reference in New Issue
Block a user