【发布时间】:2015-04-30 13:18:42
【问题描述】:
我正在尝试在 React 类中绑定一个异步函数。以前我一直在使用 co 这样做
import React from 'react';
import { bind } from 'lodash';
import { wrap } from 'co';
import ajax from 'qajax';
export default class Foo extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = bind(wrap(this.handleSubmit), this);
}
*handleSubmit(event) {
event.preventDefault();
const Data = { foo: this.state.foo };
const Result = yield ajax({ /* ... */ data: Data })
//...
}
}
效果很好。
我正在尝试重构它以使用 babel 提供的装饰器和异步函数来使代码更干净,就像这样
import React from 'react';
import { bind } from 'lodash';
import { wrap } from 'co';
import ajax from 'qajax';
function AutoBind(target, name, descriptor) {
let fn = descriptor.value;
delete descriptor.value;
delete descriptor.writable;
descriptor.get = function() {
return function () { fn.apply(this, arguments); }
}
}
export default class Foo extends React.Component {
constructor(props) {
super(props);
}
@AutoBind
async handleSubmit(event) {
event.preventDefault();
const Data = { foo: this.state.foo };
const Result = await ajax({ /* ... */ data: Data })
//...
}
}
后者的问题在于,handleSubmit 函数中的 this 引用被设置为 Window 对象,这可能是由于编译后的输出绑定了 _asyncToGenerator 函数而不是提供的生成器回调函数。编译输出sn -p如下
_createDecoratedClass(Foo, [{
key: 'handleSubmit',
decorators: [AutoBind],
value: _asyncToGenerator(function* (event) {
event.preventDefault();
//...
})
}
我知道这是一个相当新的领域,这样的问题是可以预料的,我只是想知道是否有人尝试过类似的方法并找到了解决方案,目前我将坚持以前的工作方法。
最后,AutoBind 装饰器在非异步函数上按预期工作,像这样
@AutoBind
handleScreennameChange({ target: { value }}) {
this.setState({
screen_name: value
});
}
【问题讨论】:
-
等等,你为什么不把那个吸气剂做成
function(){ return fn; }?你为什么要使用吸气剂? -
我从babeljs.io/blog/2015/03/31/5.0.0 改编了这个例子——虽然我可能不需要
标签: javascript async-await babeljs