【问题标题】:How to make a simple JSONP asynchronous request in Angular 2?如何在 Angular 2 中进行简单的 JSONP 异步请求?
【发布时间】:2016-07-17 07:33:52
【问题描述】:

我正在尝试将以下 Angular 1 代码转换为 Angular 2:

$http.jsonp('https://accounts.google.com/logout');

必须是 JSONP 请求才能跳过 CORS 策略问题。

【问题讨论】:

    标签: asynchronous typescript xmlhttprequest angular jsonp


    【解决方案1】:

    在最新版本的 Angular 中

    1. 在您的应用模块定义文件中导入 HttpClientModuleHttpClientJsonpModule 模块

       import {
           HttpClientModule,
           HttpClientJsonpModule
       } from '@angular/common/http';
      
       @NgModule({
       declarations: [
           //... List of components that you need.
       ],
       imports: [
           HttpClientModule,
           HttpClientJsonpModule,
           //...
       ],
       providers: [
           //...
       ],
       bootstrap: [AppComponent]
       })
      
    2. httpmap rxjs 运算符注入到您的服务中:

       import {Injectable} from '@angular/core';
       import {HttpClient} from '@angular/http';
       import 'rxjs/add/operator/map';
      
       @Injectable()
       export class MegaSuperService {
          constructor(private _http: HttpClient) {}
       }
      
    3. 通过以下方式发出 JSONP 请求:

       // inside your service
       this._http.jsonp('/api/get', 'callback').map(data => {
       // Do stuff.
       });
      

    在 Angular 版本 2 - 版本 4.3

    1. 在应用模块的定义文件中导入 JSONP 模块:

       import {JsonpModule} from '@angular/http';
      
       @NgModule({
       declarations: [
           //... List of components that you need.
       ],
       imports: [
           JsonpModule,
           //...
       ],
       providers: [
           //...
       ],
       bootstrap: [AppComponent]
       })
      
    2. jsonp 服务和 map rxjs 运算符注入到您的服务中:

       import {Injectable} from '@angular/core';
       import {Jsonp} from '@angular/http';
       import 'rxjs/add/operator/map';
      
       @Injectable()
       export class MegaSuperService {
          constructor(private _jsonp: Jsonp) {}
       }
      
    3. 使用“JSONP_CALLBACK”作为回调属性发出请求:

       // inside your service
       this._jsonp.get('/api/get?callback=JSONP_CALLBACK').map(data => {
       // Do stuff.
       });
      

    【讨论】:

    • 知道为什么这个“完全相同的代码”会抛出EXCEPTION: Response with status: 200 Ok for URL: null,而永远不会进入map函数吗?
    • 我收到以下错误:未捕获的 ReferenceError: __ng_jsonp____req0_finished 未定义且 JSONP 注入脚本未调用回调。任何想法?我的 api 调用有 jsonp 参数。 api.instagram.com/v1/users/self/…{myAccesToken} 我正在从 angular/http 导入 jsonp 并注入到构造函数中。我还在 app.module.ts 文件中添加了导入。
    • @MoshMage 您在 IE 和 Chrome 中都看到了这种行为吗? Chrome 对我来说工作正常,IE 在后台抛出错误但返回响应 200: OK to the subscription.
    • @GastonK 是 API 期望回调为“JSONP_CALLBACK”吗?如果 Angular 看到这个确切的字符串,它会用 __ng_jsonp____req_finished 覆盖它。见:github.com/angular/angular/blob/…
    【解决方案2】:

    Angular 4.3 及更高版本中,您应该使用 HttpClientModule,因为 JsonpModule 已被弃用。

    1. HttpClientModuleHttpClientJsonpModule 导入到您的模块中。
    2. HttpClient 注入您的服务中。
    3. 将回调键作为jsonp 方法的第二个参数传递。

    app.module.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    // Import relevant http modules
    import { HttpClientModule, HttpClientJsonpModule } from '@angular/common/http';
    
    import { AppComponent } from './app.component';
    
    import { ExampleService } from './example.service';
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        // Import relevant http modules
        HttpClientModule,
        HttpClientJsonpModule
      ],
      providers: [ExampleService],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    example.service.ts

    import { Injectable } from '@angular/core';
    // Import HttpClient class
    import { HttpClient } from '@angular/common/http';
    
    @Injectable()
    export class ExampleService {
    
      // Inject HttpClient class
      constructor(private http: HttpClient) { }
    
      getData() {
        const url = "https://archive.org/index.php?output=json&callback=archive";
    
        // Pass the key for your callback (in this case 'callback')
        // as the second argument to the jsonp method
        return this.http.jsonp(url, 'callback');
      }
    }
    

    【讨论】:

    • 谢谢。只是对这个答案的补充,我们需要将 'callback' 替换为 'JSONP_CALLBACK'。
    • @RahulUpadhyay 我已经用您的更正更新了答案。谢谢!
    • 作为一个数据点,我发现&callback=JSONP_CALLBACK 不仅是不必要的,它还破坏了一些东西——但也许那是在不同/新/旧版本的 Angular 中;无论如何,它只是“知道”添加然后出于某种原因删除回调信息。 YMMV。
    • @kcrisman 好收获!查看line 1124 of the HttpClient JSONP_CALLBACK 附加到回调参数。我现在会更新我的答案。
    • 现在有一个新问题。跨域读取阻塞 (CORB) 阻止了跨域响应
    【解决方案3】:

    如果此端点是 jsonp 兼容的,您可以使用以下内容。您需要找出用于提供 jsonp 回调的参数。在下面的代码中,我称之为c

    在调用bootstrap函数时注册JSONP_PROVIDERS后:

    import {bootstrap} from 'angular2/platform/browser'
    import {JSONP_PROVIDERS} from 'angular2/http'
    import {AppComponent} from './app.component'
    
    bootstrap(AppComponent, [ JSONP_PROVIDERS ]);
    

    然后您可以使用从构造函数注入的Jsonp 类的实例来执行您的请求:

    import {Component} from 'angular2/core';
    import {Jsonp} from 'angular2/http';
    
    @Component({
      selector: 'my-app',
      template: `
        <div>
          Result: {{result | json}}
        </div>
      `
    })
    export class AppComponent {
      constructor(jsonp:Jsonp) {
        var url = 'https://accounts.google.com/logout&c=JSONP_CALLBACK';
        jsonp.request(url, { method: 'Get' })
         .subscribe((res) => {
           (...)
         });
      }
    }
    

    查看这个问题了解更多详情:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-27
      • 1970-01-01
      • 2016-05-03
      • 1970-01-01
      • 2022-01-16
      • 1970-01-01
      • 2013-10-15
      相关资源
      最近更新 更多