使用babel将异步函数与装饰器绑定

时间:2015-04-30 13:18:43

标签: javascript async-await babeljs

我试图在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 })

        //...
    }
}

后者的问题是teh handleSubmit函数内的this引用被设置为Window对象,因为编译后的输出绑定了_asyncToGenerator函数而不是提供的生成器回调函数。编译后的输出片段如下

_createDecoratedClass(Foo, [{
        key: 'handleSubmit',
        decorators: [AutoBind],
        value: _asyncToGenerator(function* (event) {
            event.preventDefault();

            //...
        })
    }

我知道这是一个相当新的领域,这样的问题是可以预期的,我只是想知道是否有人尝试了类似的东西并找到了解决方案,暂时我会坚持以前的工作方法

最后,AutoBind装饰器在非异步函数上按预期工作,如此

@AutoBind
handleScreennameChange({ target: { value }}) {
    this.setState({
        screen_name: value
    });
}

0 个答案:

没有答案