如何修复JavaScript中的“无法读取null的属性'id'”错误?

时间:2018-12-21 04:55:52

标签: javascript graphql apollo

我正在遵循阿波罗教程。最终结果是一个交互式应用程序,允许登录的用户在即将到来的Space-X发射中预定位置。

我刚写完三个突变解析器:login,bookTrips和cancelTrip。 https://www.apollographql.com/docs/tutorial/resolvers.html#mutation

使用3个ID的对象数组作为参数来测试bookTrips会导致错误。 https://graphqlbin.com/v2/K1V7ir

测试登录解析器有效 https://graphqlbin.com/v2/K1V7ir

测试cancelTrip的工作原理 https://graphqlbin.com/v2/K1V7ir

我已经遍历我的代码几次以寻找错字。我注释掉了我的代码版本,并复制/粘贴了本教程中给出的代码,仍然出现相同的错误。

在src / resolvers.js内部

bookTrips: async (_, { launchIds }, { dataSources }) => {
        const results = await dataSources.userAPI.bookTrips({ launchIds });
        const launches = await dataSources.launchAPI.getLaunchesByIds({
            launchIds,
        });

        return {
            success: results && results.length === launchIds.length,
            message: results.length === launchIds.length
                ? 'trips booked successfully'
                : `the following launches could not be booked: ${launchIds.filter(
                    id => !results.includes(id),
                )}`,
            launches,
        };
    },
cancelTrip: async (_, { launchId }, { dataSources }) => {
        const result = dataSources.userAPI.cancelTrip({ launchId });

        if (!result) 
            return {
                success: false,
                message: 'failed to cencel trip',
            };

        const launch = await dataSources.launchAPI.getLaunchById({ launchId });
        return {
            success: true,
            message: 'trip cancelled',
            launches: [launch],
        };
    },
},

在src / datasources / launch.js内部

// returns several launches based on their respective launchIds
getLaunchByIds({ launchIds }) {
    return Promise.all(
        launchIds.map(launchId => this.getLaunchById({ launchId })),
    );
}

// method takes in a flight number and returns the data for a particular launch
    async getLaunchById({ launchId }) {
        const res = await this.get('launches', { flight_number: launchId });
        return this.launchReducer(res[0]);
    }

// transform launch data into a shape the schema expects
    launchReducer(launch) {
        return {
            id: launch.flight_number || 0,
            cursor: `${launch.launch_date_unix}`,
            site: launch.launch_site && launch.launch_site.site_name,
            mission: {
                name: launch.mission_name,
                missionPatchSmall: launch.links.mission_patch_small,
                missionPatchLarge: launch.links.mission_patch,
            },
            rocket: {
                id: launch.rocket.rocket_id,
                name: launch.rocket.rocket_name,
                type: launch.rocket.rocket_type,
            },
        };
    }

在src / datasources / user.js内部

 // Takes an object with an array of launchIds and books them for the logged in user
 async bookTrips({ launchIds }) {
  const userId = this.context.user.id;
   if (!userId) return;

   let results = [];

// for each launch id, try to book the trip and add it to the results array
// if successful
for (const launchId of launchIds) {
  const res = await this.bookTrip({ launchId });
  if (res) results.push(res);
}

return results;

}

在我的graphql操场上跑完之后

 mutation BookTrips {
  bookTrips(launchIds: [67,68,69]) {
   success
   message
   launches {
    id
   }
  }
 }

我期望获得成功消息以及刚刚预订的突变ID。

2 个答案:

答案 0 :(得分:0)

似乎找不到用户。尝试更改

async bookTrips({ launchIds }) {
    const userId = this.context.user.id;

async bookTrips({ launchIds }) {
    const userId = this.context.user && this.context.user.id;

答案 1 :(得分:0)

仅供参考,我在尝试使用 Apollo 在标头中发送授权参数时遇到了同样的错误:

  const currentUserJSON = localStorage.getItem("currentUser") || undefined;
  const currentUser =
    currentUserJSON !== undefined ? JSON.parse(currentUserJSON) : undefined;
  return {
    headers: {
      ...headers,
      ...(currentUser !== undefined
        ? { [`Authorization-User-ID`]: currentUser.id }
        : {}),
    },
  };
});

原来的错误是我正在检查 localStorage 是否返回 undefined,当它返回 null 时没有数据。

因此,当 currentUser 为 currentUser.id 时,我的逻辑试图读取 null

简单的解决方案:

// Cast nulls to undefined when fetching from localStorage
localStorage.getItem("currentUser") || undefined;