javascript - 如何在类函数中使 this 不为空?

标签 javascript this babeljs

从下面的 getPlanById 函数中,我收到 TypeError: Cannot read property 'planReducer' of null 错误。我尝试在构造函数中绑定(bind) this 并使用箭头函数。似乎两者都不起作用。还有其他事情在起作用吗?

require('dotenv').config();

const { RESTDataSource } = require('apollo-datasource-rest')
import firebaseInitialize from '../../firebase_initialize'
const firebase = firebaseInitialize()

class PlanData extends RESTDataSource {
  constructor() {
    super()
    this.baseURL = 'https://api.com/'
    this.getPlanById = this.getPlanById.bind(this)
  }
  willSendRequest(request) {
    console.log(this.context.headers)
    request.headers.set('Auth', this.context.headers.authorization);
  }
  planReducer(data) {
    return {
      id: data.plan.id,
      image: data.plan.image,
      title: data.plan.title
    }
  }
  getPlanById = async ({ planId }) => {
    const db = firebase.database()
    const ref = db.ref(`plans/${planId}`)
    ref.once("value", function(snapshot) {
      const data = snapshot.val()
      return this.planReducer(data)
    }).catch((e) => {
      console.log(e)
    });
  }
}

export default PlanData

最佳答案

this 引用您案例中的 function(snapshot) {...} 闭包。

简单的方法是在闭包外部定义 parent,然后使用 parent 而不是 this:

require('dotenv').config();

const { RESTDataSource } = require('apollo-datasource-rest')
import firebaseInitialize from '../../firebase_initialize'
const firebase = firebaseInitialize()

class PlanData extends RESTDataSource {
  constructor() {
    super()
    this.baseURL = 'https://api.com/'
    this.getPlanById = this.getPlanById.bind(this)
  }
  willSendRequest(request) {
    console.log(this.context.headers)
    request.headers.set('Auth', this.context.headers.authorization);
  }
  planReducer(data) {
    return {
      id: data.plan.id,
      image: data.plan.image,
      title: data.plan.title
    }
  }
  getPlanById = async ({ planId }) => {
    const parent = this;
    const db = firebase.database()
    const ref = db.ref(`plans/${planId}`)
    ref.once("value", function(snapshot) {
      const data = snapshot.val()
      return parent.planReducer(data)
    }).catch((e) => {
      console.log(e)
    });
  }
}

但是,您的 returnparent.planReducer(data) 行可能也在执行您不希望它执行的操作:它只是在闭包内返回,而不是 getPlanById 函数。

因此要解决这个问题,请使用async/await:

require('dotenv').config();

const {RESTDataSource} = require('apollo-datasource-rest')
import firebaseInitialize from '../../firebase_initialize'

const firebase = firebaseInitialize()

class PlanData extends RESTDataSource {
    constructor() {
        super();
        this.baseURL = 'https://api.com/';
        this.getPlanById = this.getPlanById.bind(this)
    }

    willSendRequest(request) {
        console.log(this.context.headers);
        request.headers.set('Auth', this.context.headers.authorization);
    }

    planReducer(data) {
        return {
            id: data.plan.id,
            image: data.plan.image,
            title: data.plan.title
        }
    }

    getPlanById = async ({planId}) => {
        const parent = this;
        const db = firebase.database();
        const ref = db.ref(`plans/${planId}`);
        return await new Promise((resolve) => {
            ref.once('value', function (snapshot) {
                const data = snapshot.val();
                resolve(parent.planReducer(data));
            }).catch((e) => {
                console.log(e);
                // add some sensible error handling here
                resolve(null);
            });
        });

    }
}

关于javascript - 如何在类函数中使 this 不为空?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56637495/

相关文章:

javascript - 在我的例子中如何正确使用Javascript 'this'?

jquery - $(this) 和 event.target 的区别?

javascript - 您为我们提供了节点类型 TSInstantiationExpression 的访问者,但它不是有效类型

babeljs - Ava 附加 babel 插件未运行

javascript - 将枚举从 Typescript 转换为 JavaScript 时出错

javascript - 是否有像15个谜题一样无法解决的8个谜题

javascript - 简单的 Javascript div 淡入不起作用

Java 泛型自引用 : is it safe?

javascript - 在二维中对颜色进行排序

javascript - 导出 * as blabla - 意外的 token 错误