类型错误:您在需要流的地方提供了“未定义" [英] TypeError: You provided 'undefined' where a stream was expected

查看:19
本文介绍了类型错误:您在需要流的地方提供了“未定义"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 signup() 方法的 user 提供程序的 Ionic 应用程序:

doSignup() {//将登录设置为与电子邮件相同this.account.login = this.account.email;//尝试通过我们的用户服务登录this.user.signup(this.account).subscribe((resp) => {this.navCtrl.push(MainPage);}, (错误) =>{//console.log('注册错误', err);//^^ 导致您在需要流的地方提供了‘未定义’"//this.navCtrl.push(MainPage);//无法注册让 toast = this.toastCtrl.create({消息:this.signupErrorString,持续时间:3000,位置:'顶部'});toast.present();});}

出于某种原因,这段代码从不调用成功回调,只调用错误处理程序.当它发生时,它会导致您在上面的评论中看到的错误.

我的 user.signup() 方法如下所示:

signup(accountInfo: any) {return this.api.post('register', accountInfo).share();}

我的Api 类如下所示:

import { HttpClient, HttpParams } from '@angular/common/http';从@angular/core"导入{可注射};/*** Api 是一个通用的 REST Api 处理程序.首先设置您的 API 网址.*/@Injectable()导出类 API {public static API_URL: string = 'http://localhost:8080/api';构造函数(公共 http:HttpClient){}获取(端点:字符串,参数?:任何,reqOpts?:任何){如果(!reqOpts){请求选项 = {参数:新的 HttpParams()};}//支持 GET 请求的简单查询参数如果(参数){reqOpts.params = new HttpParams();for(让 k 在参数中){reqOpts.params.set(k, params[k]);}}return this.http.get(Api.API_URL + '/' + endpoint, reqOpts);}后(端点:字符串,正文:任何,reqOpts?:任何){return this.http.post(Api.API_URL + '/' + endpoint, body, reqOpts);}put(endpoint: string, body: any, reqOpts?: any) {return this.http.put(Api.API_URL + '/' + endpoint, body, reqOpts);}删除(端点:字符串,reqOpts?:任何){return this.http.delete(Api.API_URL + '/' + endpoint, reqOpts);}补丁(端点:字符串,正文:任何,reqOpts?:任何){return this.http.put(Api.API_URL + '/' + endpoint, body, reqOpts);}}

我尝试从 user.signup() 中删除 share(),并返回 Observable,但这无济于事.

解决方案

我在使用 generator-jhipster-ionic (yo jhipster-ionic Give v3.1.2) 创建一个新项目时遇到了这个问题,遵循 Matt Raible 的 (OP) 使用 Ionic for JHipster 创建带有 OIDC 身份验证的移动应用 博客文章,但选择 JWT 身份验证而不是 OIDC.

问题的根源是问题的混合.

我在使用 livereload 服务器运行 Ionic 应用程序时遇到了问题,发生 CORS 问题并且 Angular HTTP 返回经典的 HTTP 失败响应 for (unknown url): 0 Unknown Error,其中 0 是HTTP 错误代码.然而,在目前的情况下,这个问题被 Observable 级别的错误处理隐藏了.

当您遵循 Angular 的 HttpClient #Error Details 部分建议时,并添加一个在 HTTP POST 调用上带有 catchError 操作符的 Observable 管道,您可以获得正确的 HTTP 错误详细信息.在这种情况下,而不是深入到 rxjs/util/subscribeToResult.js:71 (TS source #L80) TypeError: You provided 'undefined' where a stream is expected 默认错误情况,它转到 <代码>rx/util/subscribeToResult.js:23 (TS source #L34),错误在管道方法中得到正确处理.

跟踪 Observable 调用后,我发现当前默认的身份验证拦截器,如本模板所示 src/providers/auth/auth-interceptor.ts 捕获 HTTP 错误 401 并且不对其他人做任何事情,基本上是静音并阻止其传播.

TL;DR 在 JWT 的情况下,解决方案是简单地删除 src/providers/auth/auth-interceptor.ts .catch(...) 块,允许错误传播到 login.service.ts,并在它的 this.authServerProvider.login(credentials).subscribe((data) => {... }, (err) => { ... }) 错误回调.

我相信您的 OIDC 案例、其注册方法和错误回调的问题和解决方案可能相同.

甚至更多,因为可以在第一篇帖子评论中提到的入门示例中找到相同的 .catch 代码:ionic-jhipster-starter - auth->#31por>

I have an Ionic app that has a user provider with a signup() method:

doSignup() {
  // set login to same as email
  this.account.login = this.account.email;
  // Attempt to login in through our User service
  this.user.signup(this.account).subscribe((resp) => {
    this.navCtrl.push(MainPage);
  }, (err) => {
    //console.log('error in signup', err);
    // ^^ results in 'You provided 'undefined' where a stream was expected'
    //this.navCtrl.push(MainPage);

    // Unable to sign up
    let toast = this.toastCtrl.create({
      message: this.signupErrorString,
      duration: 3000,
      position: 'top'
    });
    toast.present();
  });
}

For some reason, this code never calls the success callback, only the error handler. When it does, it results in the error you see in the comment above.

My user.signup() method looks as follows:

signup(accountInfo: any) {
  return this.api.post('register', accountInfo).share();
}

My Api class looks as follows:

import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';

/**
 * Api is a generic REST Api handler. Set your API url first.
 */
@Injectable()
export class Api {
  public static API_URL: string = 'http://localhost:8080/api';

  constructor(public http: HttpClient) {
  }

  get(endpoint: string, params?: any, reqOpts?: any) {
    if (!reqOpts) {
      reqOpts = {
        params: new HttpParams()
      };
    }

    // Support easy query params for GET requests
    if (params) {
      reqOpts.params = new HttpParams();
      for (let k in params) {
        reqOpts.params.set(k, params[k]);
      }
    }

    return this.http.get(Api.API_URL + '/' + endpoint, reqOpts);
  }

  post(endpoint: string, body: any, reqOpts?: any) {
    return this.http.post(Api.API_URL + '/' + endpoint, body, reqOpts);
  }

  put(endpoint: string, body: any, reqOpts?: any) {
    return this.http.put(Api.API_URL + '/' + endpoint, body, reqOpts);
  }

  delete(endpoint: string, reqOpts?: any) {
    return this.http.delete(Api.API_URL + '/' + endpoint, reqOpts);
  }

  patch(endpoint: string, body: any, reqOpts?: any) {
    return this.http.put(Api.API_URL + '/' + endpoint, body, reqOpts);
  }
}

I tried removing share() from user.signup(), and returning Observable<any>, but that doesn't help.

解决方案

I faced this issue when creating a new project using generator-jhipster-ionic (yo jhipster-ionic giving v3.1.2), following Matt Raible's (OP) Use Ionic for JHipster to Create Mobile Apps with OIDC Authentication blog article, but choosing JWT authentication instead of OIDC.

The origin of the issue was a mix of problems.

I had the issue when running a Ionic app with the livereload server, CORS issues happening and Angular HTTP returning the classic HTTP failure response for (unknown url): 0 Unknown Error, where 0 is the HTTP error code. However, in the current case the issue was hidden by bad error handling at the Observable level.

When you follow Angular's HttpClient #Error Details section advices, and add an Observable pipe with a catchError operator on the HTTP POST call, you can get the proper HTTP error details. In this case, instead of going down to the rxjs/util/subscribeToResult.js:71 (TS source #L80) TypeError: You provided 'undefined' where a stream was expected default error case, it goes to rx/util/subscribeToResult.js:23 (TS source #L34), and the error is handled properly in the piped method.

After following the Observable calls, I found that the current default authentication interceptor, as seen in this template src/providers/auth/auth-interceptor.ts catches HTTP error 401 and does nothing for the others, basically muting them and preventing their propagation.

TL;DR In the JWT case, the solution is to simply remove the src/providers/auth/auth-interceptor.ts .catch(...) block, allowing error propagation to login.service.ts, and in its this.authServerProvider.login(credentials).subscribe((data) => { ... }, (err) => { ... }) error callback.

I believe the issue and solution could be the same for your OIDC case, its signup method, and error callback.

[Edit] Even more since the same .catch code can be found in the starter example mentioned in the first post comments: ionic-jhipster-starter - auth-interceptor.ts#L31

这篇关于类型错误:您在需要流的地方提供了“未定义"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆