订阅未定义的错误处理 - Apollo 和 Angular 2

Posted

技术标签:

【中文标题】订阅未定义的错误处理 - Apollo 和 Angular 2【英文标题】:Error Handling For Undefined From Subscription - Apollo and Angular 2 【发布时间】:2017-12-26 21:03:04 【问题描述】:

我在使用 Apollo 查询 GraphQL 端点的 Angular 2 中有以下代码:

getStudentPersonalDetails(studentId?: number) 
    console.log(studentId)
    this.apollo.watchQuery<QueryResponse>(
        query: StudentPersonalDetailsQ,
        variables: 
            studentId: studentId
        
    ).subscribe(( data ) => 
        if (typeof data.allStudentDetails != 'undefined') 
            console.log(data)
            this.loading = data.loading;
            this.personalDetails.studentId = data.allStudentDetails.nodes[0].studentPk;
            this.personalDetails.firstName = data.allStudentDetails.nodes[0].firstName;
            this.personalDetails.middleName = data.allStudentDetails.nodes[0].middleName;
            this.personalDetails.lastName = data.allStudentDetails.nodes[0].lastName;
            this.personalDetails.preferredName = data.allStudentDetails.nodes[0].preferredName;
            this.personalDetails.onlyOneName = data.allStudentDetails.nodes[0].onlyOneName;
            this.personalDetails.dob = data.allStudentDetails.nodes[0].dob;
            this.personalDetails.sex = data.allStudentDetails.nodes[0].sex;
            this.personalDetails.birthCountry = data.allStudentDetails.nodes[0].metaCountryByBirthCountryId.countryName;
            this.personalDetails.passportCountry = data.allStudentDetails.nodes[0].metaCountryByPassportCountryId.countryName;
            this.personalDetails.passportNumber = data.allStudentDetails.nodes[0].passportNumber;
            this.personalDetails.contactCountry = data.allStudentDetails.nodes[0].metaCountryByContactCountryId.countryName;
            this.personalDetails.personalEmail = data.allStudentDetails.nodes[0].personalEmail;
            console.log(data.allStudentDetails);
        
    , (error) => 
        console.log('there was an error sending the query', error);
    );

我正在通过故意传递一个不存在的学生 ID 并因此返回 Cannot read property 'studentPk' of undefined 来测试该方法。但是,我试图通过检测 allStudentDetails 是否未定义并转到错误捕获来避免此错误。

如何添加错误处理来处理undefined 数据,然后将其从服务适当地提供给将使用烤面包机显示用户友好错误的组件?

【问题讨论】:

看起来data.allStudentDetails 实际上不是未定义的,而是nodes 数组未定义。登录typeof data.allStudentDetails会得到什么? 我得到一个长度为 0 的 nodes 数组的对象。 【参考方案1】:

如果我理解这个问题,您可以先通过map 运行响应并在该级别抛出错误。类似的东西(当然,这是未经测试的):

getStudentPersonalDetails(studentId?: number) 
    console.log(studentId)
    this.apollo.watchQuery<QueryResponse>(
        query: StudentPersonalDetailsQ,
        variables: 
            studentId: studentId
        
    ).map((data) => 
        console.log(data.allStudentDetails);
        if (typeof data.allStudentDetails.nodes[0] === 'undefined') 
            // Could also check if array length is 0
            // data.allStudentDetails.nodes.length <= 0
            throw new Error('This student does not exist!');
        
        return data;
    ).subscribe((data) => 
        console.log(data)
        this.loading = data.loading;
        this.personalDetails.studentId = data.allStudentDetails.nodes[0].studentPk;
        this.personalDetails.firstName = data.allStudentDetails.nodes[0].firstName;
        this.personalDetails.middleName = data.allStudentDetails.nodes[0].middleName;
        this.personalDetails.lastName = data.allStudentDetails.nodes[0].lastName;
        this.personalDetails.preferredName = data.allStudentDetails.nodes[0].preferredName;
        this.personalDetails.onlyOneName = data.allStudentDetails.nodes[0].onlyOneName;
        this.personalDetails.dob = data.allStudentDetails.nodes[0].dob;
        this.personalDetails.sex = data.allStudentDetails.nodes[0].sex;
        this.personalDetails.birthCountry = data.allStudentDetails.nodes[0].metaCountryByBirthCountryId.countryName;
        this.personalDetails.passportCountry = data.allStudentDetails.nodes[0].metaCountryByPassportCountryId.countryName;
        this.personalDetails.passportNumber = data.allStudentDetails.nodes[0].passportNumber;
        this.personalDetails.contactCountry = data.allStudentDetails.nodes[0].metaCountryByContactCountryId.countryName;
        this.personalDetails.personalEmail = data.allStudentDetails.nodes[0].personalEmail;
    , (error) => 
        console.log(error.message);
    );

【讨论】:

我收到一个很长的错误。第一部分是:The 'this' context of type 'ApolloQueryObservable&lt;QueryResponse&gt;' is not assignable to method's 'this' of type 'Observable&lt;ApolloQueryResult&lt;QueryResponse&gt;&gt;'. 对,对不起,我错过了。 this.loading 必须在订阅方法中。我会更新答案。

以上是关于订阅未定义的错误处理 - Apollo 和 Angular 2的主要内容,如果未能解决你的问题,请参考以下文章

我的 Apollo 服务器的订阅不起作用:无法读取未定义的属性“标题”

未捕获的错误:react-apollo 仅支持每个 HOC 的查询、订阅或突变

Apollo 订阅解析器永远不会激活?

订阅字段必须返回 Async Iterable。收到:未定义

RelayObservable:未处理的错误 TypeError:无法读取 React 和 Relay 中未定义的属性“订阅”

Apollo 订阅未在客户端监听新数据