【问题标题】:Angular 2 Http provider's observable subscribe not firingAngular 2 Http 提供者的可观察订阅未触发
【发布时间】:2017-07-23 17:53:24
【问题描述】:

我很难让 .subscribe() 方法在 Angular 2 中触发一个可观察对象。我的设置是一个提供程序,它向 Http Service 注入一个方法,该方法返回控制器可以与之交互的可观察对象,并订阅到。

我不清楚为什么当方法返回可观察对象并且控制器将订阅链接到该对象时订阅不会触发。非常感谢任何帮助。

用户提供者

@Injectable()
export class UserResource {

    constructor( protected http: Http ) {}

    public getUsers(): Observable<User[]> {
        return this.http.get( '/api/users' )
            .map( (response: Response) => <User[]>response.json() )
            .catch( (error: Response | any) => {
                console.log( error );
                return Observable.throw( error );
            });
    }
}

用户控制器

export class UsersController {
    public usersEnrolled: User[]   = [];
    public usersUnenrolled: User[] = [];

    constructor( private userResource: UserResource ) {}

    ngOnInit() {
        this.userResource.getUsers()
            .subscribe(( users: User[] ) => {
                console.log( 'users', users ); // does not fire
                this.usersUnenrolled = users.filter( (user: User) => !user.isEnrolled );
                this.usersEnrolled   = users.filter( (user: User) => user.isEnrolled );
            },
            ( error ) => console.log( 'error', error ),
            () => console.log( 'completed' )
        );
    }
}

更新的订阅包括错误和完成的回调

请注意,为了代码简洁,我排除了 import 语句。

【问题讨论】:

  • 不确定这是否是问题所在,但请尝试使用完整的 url 请求,例如:this.http.get('http://localhost:8080/api/users')(或任何主机名)
  • thx @lenny 为了简洁起见,我保留了它,但它确实在我的实际代码中包含主机。 :)
  • 或者类型有问题,使用any而不是User会发生什么?
  • 其实调试这个问题的更清晰的方法是在你的Sources面板中设置一个调试断点,或者在你想要开始的地方添加debugger;语句并遵循执行路径。跨度>
  • .map( (response) =&gt; console.log(response.json()) ) 打印出来的是什么?

标签: angular rxjs angular2-observables


【解决方案1】:

您应该在订阅中添加一个错误函数,以便了解原因。

.subscribe(
     users: User[] => console.log( 'users', users ),
     error => console.log('error',error),
     () => console.log('completed')
);

您只是传入“下一个”函数。我发现使用 subscribe() 的所有三个函数很有帮助

【讨论】:

  • 很公平。我正在按照您的建议执行此操作,并且没有将任何内容写入控制台。我什至在ngOnInit 中添加了一个console.log 语句作为健全性检查,以确保正在调用对我的UserProvider.getUsers().subscribe() 的调用;是的。
【解决方案2】:

我是个笨蛋。该代码有效,这是因为http.get() 中的 URL 与我们为来自MockBackend 的模拟响应定义的 URL 不匹配。我的道歉,大家。一旦我考虑了不匹配的 URL,它就会按预期工作。感谢您的帮助。

不确定如何将此标记为已接受的答案?

【讨论】:

    【解决方案3】:

    您正在订阅用户:User[],但您正在映射到 json。如果你这样做:

    .subscribe(users => {
    console.log(users);
    }
    

    你有任何东西写入控制台吗?

    【讨论】:

    • 没有写入控制台。我按照上面Jeff Justice 的建议更新了回调(上面和我的实际代码中)。另外,我更新了您的建议,但没有修复它。 :(
    【解决方案4】:

    可能相关,我从未见过您在服务中包含的构造函数模式;即调用super()。 Angular 通过简单地将它作为参数包含在构造函数中来为您处理这个问题。然后将 constructor 主体留空。

    通常,我会像这样实例化我的服务类:

    import { Http, Response } from "@angular/http";
    
    export class UserResource {
    
      constructor(private http: Http) {}
    
      getUsers(): Observable<User[]> {
        //
      }
    }
    

    但我会重申我的评论:use source breakpoints if using Chromedebugger; 声明,这将使正在发生的事情更加更加清晰。如果你有源映射,你可以在 TypeScript 源中放置断点。

    【讨论】:

    • 我的错。我的 UserResource 正在扩展自定义 ApiResource 类。我将继续从我的示例代码中删除它,因为它可能不相关。
    • @TomDoe 在http 上调用了超级方法并且它的http 不起作用这一事实可能是高度相关的。如果它不是您的来源实际所做的,请不要将其从问题中删除。 :)
    • 哈!我也从我的代码中删除了它,以查明为什么这不起作用。删除它没有效果。 :(
    • 我很感激 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-19
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    相关资源
    最近更新 更多