1

I am dealing with authentication headers, one solution is to create a child class extends Http from 'angular2/http' and add default auth headers. I am using the same code from github, but it throws EXCEPTION: TypeError: backend.createConnection is not a function in [null] code here. But when I change it back to angular2/http, everything works fine. I cannot find any information about this exception message. Thanks for help!

Updates: I am using the same way the sample does. This is my service:

import {Injectable} from 'angular2/core';
// import {Http} from 'angular2/http';
import {Headers, Response} from 'angular2/http';
import {Http} from '../common/http';
import {Category} from '../model/category';
import 'rxjs/add/operator/map';

@Injectable()
export class CategoryService {
  constructor(private http:Http) {}
  getCategories() {
      return this.http.get('http://www.google.com')
      .map(res => res.json());
  }

  getCategory(id: string) {
      return this.http.get('http://localhost:8080/api/category/'+id)
      .map(res => res.json());
  }
}

This is my /commom/http

import {Observable} from "rxjs/Observable";
import {Injectable} from "angular2/core";
import {Http as NgHttp,  RequestOptionsArgs, RequestOptions,  Headers, Response, ConnectionBackend} from "angular2/http";

const mergeAuthToken = (options:RequestOptionsArgs) => {
  let newOptions = new RequestOptions({}).merge(options);
  let newHeaders = new Headers(newOptions.headers);
  let access_token = localStorage.getItem('access_token');
  newHeaders.set('Authorization', 'bearer '+ access_token);
  newHeaders.set('Accept', 'application/json');
  newHeaders.set('Content-Type', 'application/json');
  newOptions.headers = newHeaders;
  return newOptions;
};

@Injectable()
export class Http extends NgHttp {
    constructor(_backend: ConnectionBackend, _defaultOptions: RequestOptions) {
        super(_backend, _defaultOptions);
    }
  get(url:string, options?:RequestOptionsArgs):Observable<Response> {
      return super.get(url, mergeAuthToken(options));
  }

  post(url:string, body:string, options?:RequestOptionsArgs):Observable<Response> {
    return super.post(url, body, mergeAuthToken(options));
  }...
}

This is part of my app.component:

import { Http } from '../common/http';
import { SecurityRouterOutlet } from '../router/securityRouter';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router';
import {HTTP_PROVIDERS, ConnectionBackend } from 'angular2/http';

@Component({
    selector: 'my-app',
    templateUrl: 'app/view/app.component.html',
    styleUrls: ['app/view/app.component.css'],
    directives: [SecurityRouterOutlet, ROUTER_DIRECTIVES],
    providers: [
        ROUTER_PROVIDERS,
        HTTP_PROVIDERS,
        CategoryService,
        LoginService,
        ConnectionBackend,
        Http
    ]
})

If more code detail is needed, please let me know. Thanks!

Update2 As @Thierry Templier suggested, I change Http to AuthHttp in my common/http file, so as category service and app.component.ts, but this doesn't help.

The full stack of exception:

TypeError: backend.createConnection is not a function  angular2.dev.js:23877 
    at httpRequest (http.dev.js:941)
    at AuthHttp.Http.get (http.dev.js:980)
    at AuthHttp.get (http.ts:24)
    at CategoryService.getCategories (category.service.ts:16)
    at DashboardComponent.ngOnInit (dashboard.component.ts:15)
    at AbstractChangeDetector.ChangeDetector_HostDashboardComponent_0.detectChangesInRecordsInternal (viewFactory_HostDashboardComponent:21)
    at AbstractChangeDetector.detectChangesInRecords (angular2.dev.js:9609)
    at AbstractChangeDetector.runDetectChanges (angular2.dev.js:9592)
    at AbstractChangeDetector._detectChangesContentChildren (angular2.dev.js:9665)
    at AbstractChangeDetector.runDetectChanges (angular2.dev.js:9593)

The dashboard.component:

import { Component, OnInit } from 'angular2/core';
import { Router } from 'angular2/router';
import { Category } from '../model/category';
import { CategoryService } from '../service/category.service';

@Component({
    selector: 'my-dashboard',
    templateUrl: 'app/view/dashboard.component.html',
    styleUrls: ['app/view/dashboard.component.css']
})
export class DashboardComponent implements OnInit {
    categories: Category[] = [];
    constructor(private _router: Router, private _categoryService: CategoryService) { }
    ngOnInit() {
     this._categoryService.getCategories().subscribe(
          data => { this.categories = data },
          err => console.error(err)
      );
    }
    gotoDetail(category: Category){
        let link = ['CategoryDetail', { id: category.id }];
        this._router.navigate(link);
    }
}

I am using the latest version:

{
    "name": "angular2quickstart",
    "version": "1.0.0",
    "scripts": {
    "postinstall": "npm run typings install",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "lite": "lite-server",
    "start": "concurrent \"npm run tsc:w\" \"npm run lite\" ",
    "typings" : "typings"
},
  "license": "ISC",
"dependencies": {
    "angular2": "2.0.0-beta.13",
    "systemjs": "0.19.25",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.35.0",
    "reflect-metadata": "0.1.3",
    "rxjs": "5.0.0-beta.4",
    "zone.js": "0.6.9"
},
"devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.0.1",
    "typescript": "^1.7.5",
    "typings": "^0.7.12"
    }
}
4

1 回答 1

0

useClass定义关联的提供者时不能使用,但是useFactory这样:

bootstrap(AppComponent, [
  HTTP_PROVIDERS,
  provide(Http, {
    useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => new CustomHttp(backend, defaultOptions),
    deps: [XHRBackend, RequestOptions]
  })
]);

这样,您将提供要注入的后端。

编辑

我发现您定义班级的方式存在问题。你应该尝试这样的事情:

export class CustomHttp extends Http {
  (...)
}

并将其注册到上述provide函数中。

于 2016-04-12T14:17:20.307 回答