简体   繁体   中英

Use ECMAScript 6 arrow functions as class methods

I'm testing my code with node v8.9.4

I want to use class methods in my promises chain. But this fails with an error: (node:68487) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot read property 'attr' of undefined

const fsp = require('fs-promise');

class MyClass {
    constructor() {
        this.attr = 'value';
    }

    promiseMe() {
        console.log(this.attr);
    }

    main() {
        fsp.readdir('.').then(this.promiseMe);
    }
}

new MyClass().main();

So I try to use arrow functions as class methods. But defining an arrow function as a class method is syntactically not correct: Unexpected token =

promiseMe = () =>  {
    console.log(this.attr);
}

This works, but it is really ugly:

const fsp = require('fs-promise');

class MyClass {
    constructor() {
        this.attr = 'value';
        this.promiseMe = () => {console.log(this.attr);}
    }

    main() {
        this.promiseMe();
    }
}

new MyClass().main();

So how can I use class methods in promises?

There is another question regarding this topic: How to use arrow functions (public class fields) as class methods? Unfortunately this doesn't work with my node.js setup.

Right this is because your context is incorrect within your Promise. One method is to bind this to your Promise context. In your example you would call it like fsp.readdir('.').then(this.promiseMe.bind(this));

Alternatively, if you're using this more often, you can bind it in your constructor:

this.promiseMe = this.promiseMe.bind(this)

This will bind it in your class so that you no longer need to bind every time you call!

An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

You are getting TypeError: Cannot read property 'attr' of undefined because this is not referencing your class instance.

It looks like you've already figured out what options you have when it comes to the class syntax. But I suggest that you ask yourself the whether the class syntax/mechanism is actually providing something you need.

It may well be the case that you can accomplish everything you need by using a factory function. This avoids all the ugly quirks of using this :

const fsp = require('fs-promise');

function myClass() {
    let attr = 'value';

    const promiseMe = () => console.log(attr);
    const main = () => fsp.readdir('.').then(promiseMe);

    return { promiseMe, main };
}

myClass().main();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM