Как получить, чтобы это не было нулевым в функции класса? - PullRequest
0 голосов
/ 17 июня 2019

При использовании функции getPlanById, приведенной ниже, я получаю ошибку TypeError: Cannot read property 'planReducer' of null.Я попытался связать 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

1 Ответ

1 голос
/ 17 июня 2019

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)
    });
  }
}

Однако, ваша строка return parent.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);
            });
        });

    }
}
...