【问题标题】:Angular2 Http RequestAngular2 Http 请求
【发布时间】:2015-11-12 20:06:47
【问题描述】:

您好,我正在尝试使用 Angular2 中的 HTTP 模块发出获取请求。

Typescript (1.5) 中一切正常,但Chrome 在控制台中显示以下错误:

EXCEPTION: Error during instantiation of EntryList!. ORIGINAL
EXCEPTION: TypeError: Cannot read property 'merge' of undefined
ORIGINAL STACKTRACE: TypeError: Cannot read property 'merge' of undefined
at mergeOptions (angular2.dev.js:27991)  
at execute.Http.get (angular2.dev.js:28052)  
at EntryService.getEntries (services.js:17)
at new EntryList (entry-list.js:20)

Services.ts

/// <reference path="../typings/angular2/angular2.d.ts" />
import { Http, Observable } from "angular2/angular2"

export class EntryService {
    private _entries: Array<string>;
    private _http : Http;

    constructor() {     
        this._entries = ["test1", "test2", "test3"];
        this._http = new Http;      
    }

    get Entries() : Array<string> {
        return this._entries;
    }

    getEntries()
    {
        console.log(this._http);
        return this._http.get('http://localhost:53338/api/decisions')       
            .toRx()
            .map((response) => { 
                response.json()
            });     
    }
}

entry-list.ts

/// <reference path="../typings/angular2/angular2.d.ts" />
/// <reference path="../modules/services.ts" />

import { Component, View, NgFor } from "angular2/angular2"
import { EntryService } from "modules/services"

@Component({
    selector: 'entry-list'  
})
@View({
    directives: [ NgFor ],
    templateUrl: "../views/entry-list.html" 
})
export class EntryList {
    entries: Array<string>; 

    constructor(public service: EntryService) {     
        this.entries = this.service.Entries;
        this.service.getEntries().subscribe((response) => {     
            console.log(response);
        }); 
    }
}

app.ts

/// <reference path="typings/angular2/angular2.d.ts" />
/// <reference path="components/entry-list.ts" />
/// <reference path="modules/services.ts" />

import { Component, View, bootstrap, NgFor } from "angular2/angular2"
import { EntryList } from "components/entry-list"
import { EntryService } from "modules/services"

@Component({
    selector : "app",
    bindings: [ EntryService ]  
})
@View({
    directives: [ EntryList ],
    templateUrl: "views/app.html"   
})
class App { 
    constructor() {
        console.log('hit');
    }
}

bootstrap(App);

index.html

<html>
    <head>
        <title>SCM</title>
        <script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.88/traceur-runtime.js"></script>
        <script src="https://jspm.io/system@0.16.js"></script>      
        <script src="https://code.angularjs.org/2.0.0-alpha.34/angular2.dev.js"></script>
    </head>
    <body>
        <app></app>
        <script>System.import('app')</script>
    </body>
</html> 

我确实查看了angular.io 站点上的 API 文档,但看不出有什么问题。

更新

Services.ts

/// <reference path="../typings/angular2/angular2.d.ts" />
import { Http, Observable, httpInjectables } from "angular2/angular2"

export class EntryService {
    private _entries: Array<string>;    

    constructor(private http: Http) {       
        this._entries = ["test1", "test2", "test3"];            
    }

    get Entries() : Array<string> {
        return this._entries;
    }

    getEntries()
    {
        console.log(this.http);
        return this.http.get('http://localhost:53338/api/decisions')        
            .toRx()
            .map((response) => { 
                response.json()
            });     
    }
}

entry-list.ts

/// <reference path="../typings/angular2/angular2.d.ts" />
/// <reference path="../modules/services.ts" />

import { Component, View, NgFor, Http, httpInjectables } from "angular2/angular2"
import { EntryService } from "modules/services"

@Component({
    selector: 'entry-list',
    bindings : [ Http, httpInjectables ]
})
@View({
    directives: [ NgFor ],
    templateUrl: "../views/entry-list.html" 
})
export class EntryList {
    entries: Array<string>; 

    constructor(public service: EntryService) {     
        this.entries = this.service.Entries;
        this.service.getEntries().subscribe((response) => {     
            console.log(response);
        }); 
    }
}

app.ts

/// <reference path="typings/angular2/angular2.d.ts" />
/// <reference path="components/entry-list.ts" />
/// <reference path="modules/services.ts" />

import { Component, View, bootstrap, NgFor, Http, httpInjectables } from "angular2/angular2"
import { EntryList } from "components/entry-list"
import { EntryService } from "modules/services"

@Component({
    selector : "app",
    bindings: [ EntryService, Http, httpInjectables ]   
})
@View({
    directives: [ EntryList ],
    templateUrl: "views/app.html"   
})
class App { 
    constructor() {
        console.log('hit');
    }
}

bootstrap(App);

index.html没有任何更改

编辑:我的 services.ts 文件更改以使其正常工作:

/// <reference path="../typings/angular2/angular2.d.ts" />
import { Injector, Http, httpInjectables } from "angular2/angular2"

export class EntryService {
    private _entries: Array<string>;    
    private http: Http;

    constructor() {     
        this._entries = ["test1", "test2", "test3"];        

        var injector = Injector.resolveAndCreate([
                httpInjectables,
                Http
            ]);
        this.http = injector.get(Http);                 
    }

    get Entries() : Array<string> {
        return this._entries;
    }

    getEntries()
    {       
        return this.http.get('http://localhost:53338/api/decisions')        
            .toRx()
            .map(response => response.json());      
    }
}

【问题讨论】:

    标签: javascript angular typescript angular2-http


    【解决方案1】:

    您真的想为 CRUD/HTTP 请求使用另一个库吗? **

    我强烈推荐 es6 de-facto fetch。它不仅是 在我看来,到目前为止比 angular2/http 更简单,但 现在和未来版本中的标准。

    ** 它也适用于 safari、chrome、ie-edge 和 firefox。

    【讨论】:

    • 一个例子将有助于支持您的案例
    【解决方案2】:

    您不应该自己实例化 Http,而是将其注入:

    public constructor(http : Http) {
        this.http = http;
    }
    

    文档说:

    Http 可作为可注入类使用,具有执行 http 请求的方法。

    因此,如果您自己实例化它,我不确定结果是什么,但由于某些未定义的内部结构,它无法以某种方式执行 get 请求。

    编辑:添加更多来源。

    @Injectable()
    export class Http {
        constructor(protected _backend: ConnectionBackend, protected _defaultOptions: RequestOptions) {}
    
        /**
         * Performs a request with `get` http method.
         */
        get(url: string, options?: RequestOptionsArgs): EventEmitter {
            return httpRequest(this._backend, new Request(mergeOptions(this._defaultOptions, options, RequestMethods.GET, url)));
      }
    }
    

    在这里,我添加了来自 github 存储库的 Http 类的一小部分。您可以看到 _backend 和 _defaultOptions 在您没有提供的构造函数中给出,并且 get() 方法将基于 options 参数和构造函数中给出的 _defaultOptions 为请求构建选项,因为您没有提供这些,我相信它会在您可以在此处找到的 mergeOptions 调用中崩溃:

    function mergeOptions(defaultOpts, providedOpts, method, url): RequestOptions {
      var newOptions = defaultOpts;
      if (isPresent(providedOpts)) {
        // Hack so Dart can used named parameters
        newOptions = newOptions.merge(new RequestOptions({
          method: providedOpts.method,
          url: providedOpts.url,
          search: providedOpts.search,
          headers: providedOpts.headers,
          body: providedOpts.body,
          mode: providedOpts.mode,
          credentials: providedOpts.credentials,
          cache: providedOpts.cache
        }));
      }
      if (isPresent(method)) {
        return newOptions.merge(new RequestOptions({method: method, url: url}));
      } else {
        return newOptions.merge(new RequestOptions({url: url}));
      }
    }
    

    函数的最后一个 if/else。更多信息源文件位于here

    【讨论】:

    • 感谢您的回答。我想尝试的第一件事是将 Http 类注入到我的 EntryService 类中。正如您从上面的代码中看到的那样,有 3 个单独的文件,我知道在 Component 注释中使用 bindings 属性将使该对象可用于整个应用程序的注入,我尝试在那里指定 Http 类进行注入,但我得到了如果我尝试注入,我的 EntryService 构造函数上的错误。你知道如何让 EntryService 的 Http 对象可注入吗?
    • 其实我只是改了代码。并且没有错误,打字稿编译器和chrome内部都没有错误,但应用程序不起作用。
    • 您可以从 angular2 导入 httpInjectables 并将其直接传递给您的引导程序调用,这是我自己成功使用的方法,目前似乎是经典方法。你能更新你的代码以反映最新的变化吗?
    • 我已经更新了代码,我也尝试将 Http 对象传递到引导调用中,但没有成功(尽管上面的代码中没有)。
    • 只需在引导程序中提供 httpInjectables,并在您的服务中仅包含 Http。然后您不再需要将其绑定到您的应用程序注入器。您能否尝试设置一个 plnkr 并重现该问题?
    猜你喜欢
    • 2016-10-25
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 2016-05-14
    • 2017-03-12
    • 1970-01-01
    相关资源
    最近更新 更多