【发布时间】:2018-06-13 09:20:39
【问题描述】:
源代码
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { createStore, applyMiddleware, compose } from 'redux';
import { Provider } from 'react-redux';
import ReduxThunk from 'redux-thunk';
import reducer from './redux';
const body = document.querySelector('body'),
composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose,
store = createStore(reducer, composeEnhancers(applyMiddleware(ReduxThunk)));
ReactDOM.render(<Provider store={store}><App/></Provider>, body);
App.js
import React from 'react';
import Shortcut from './Shortcut';
export default class App extends React.PureComponent {
render() {
return <Shortcut/>;
}
}
Shortcut.js
import React from 'react';
import { connect } from 'react-redux';
import { print_date_async } from './redux';
class Shortcut extends React.PureComponent {
componentDidMount() {
window.addEventListener('keydown', (event) => {
if (event.keyCode === 13) {
this.props.print_date_async({ date: new Date().toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1") });
}
});
}
render () {
return null;
}
}
function mapDispatchToProps(dispatch) {
return {
print_date_async: (date) => dispatch(print_date_async(date))
};
}
Shortcut = connect(undefined, mapDispatchToProps)(Shortcut);
export default Shortcut;
redux.js
import { createAction, handleActions } from 'redux-actions';
export const print_date = createAction('print_date');
export function print_date_async (payload) {
return async (dispatch) => {
try {
await wait_async();
dispatch(print_date({ date:payload.date }));
}
catch (exeption) {
console.error(exeption);
}
};
}
const initial_state = { };
export default handleActions({
print_date: (state, action) => {
console.log(action.payload.date);
return { ...state }
}
}, initial_state);
function wait_async (number) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, Math.floor(Math.random() * 10000)); // 0000 ~ 9999
});
};
问题
https://codesandbox.io/s/l7y4rn61k9
以我创建的程序为例,当你按下回车时,你按下回车的时间会在随机几秒后输出。
我希望在调用一个异步动作创建者之后调用下一个动作创建者。
如果按住回车键,第一次按下的结果也可以稍后打印。
01:42:48
01:42:48
01:42:47
01:42:47
01:42:47
01:42:47
01:42:48
我考虑导出变量来检查状态,但我不喜欢它。我也不喜欢检查按键之间的间隔。
我想通过下面的方式来实现,但是实现起来并不容易。如果你知道这件事,请回答。感谢阅读!
window.addEventListener('keydown', (event) => {
if (event.keyCode === 13) {
if (!this.proceeding) {
this.proceeding = true;
(async () => {
await this.props.print_date_async({ date: new Date().toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1") });
this.proceeding = false;
})();
}
}
});
解决
我只需要在使用 redux-thunk 时返回 promise 对象。
export function print_date_async (payload) {
return (dispatch) => new Promise(async (resolve, reject) => {
try {
await wait_async();
dispatch(print_date({ date:payload.date }));
resolve();
}
catch (exeption) {
console.error(exeption);
reject(exeption);
}
});
}
我知道 async() 返回 promise 对象,所以你不必用 promise 包装。
【问题讨论】:
-
await仅在包含的函数内阻塞。同时,async函数返回一个承诺,并且该函数之外的其他代码继续运行。因此,您的await this.props.print_date_async()不会阻止其他 keydown 事件处理程序触发和启动。我不认为你可以用 promises 和await完全解决这个问题,因为await无法阻止下一个 keydown 事件触发。我认为您必须对传入的 keydown 事件进行排队,并在前一个事件完成后处理下一个事件。 -
我对您的代码感到困惑。
print_date_async()返回一个函数。我看不到您实际调用该函数的位置。我看到您在等待一个没有多大意义的函数引用。你应该在等待一个承诺。 -
@jfriend00 感谢您的回答。 :) 你说的对。有一些事件处理程序是可以的,除非顺序混合,否则无法执行。我不明白您看不到该函数的调用位置。它在 [if (event.keyCode === 13)] 下面的行中调用。
-
调用
this.props.print_date_async()只是返回一个函数。它不会调用返回的函数。 -
@jfriend00 谢谢。它是动作创建者返回函数。我认为在 redux-thunk 中调用了返回的函数。我知道我需要知道我可以返回 promise 对象来实现所需的功能。但我对此一无所知,所以我问了。
标签: javascript reactjs redux es6-promise redux-thunk