简体   繁体   中英

http.get() fails as Promise and Observable

I have two simple services. Both should return the result of a REST API.

Originally I've started with a Promise. I could not figure out, why toPromise() was not found (same problem as here .

So I tried to switch to Observable. The problem is similar: map() could not be found.

Let me give you plenty of code...

// package.json
{
  "name": "mvc-angular-2",
  "version": "0.0.1",
  "license": "ISC",
  "scripts": {
    "start": "tsc && concurrently \"npm run tsc:w\" ",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "typings": "typings"
  },
  "dependencies": {
    "@angular/common": "2.0.0-rc.4",
    "@angular/compiler": "2.0.0-rc.4",
    "@angular/core": "2.0.0-rc.4",
    "@angular/forms": "0.2.0",
    "@angular/http": "2.0.0-rc.4",
    "@angular/platform-browser": "2.0.0-rc.4",
    "@angular/platform-browser-dynamic": "2.0.0-rc.4",
    "@angular/router": "3.0.0-beta.1",
    "@angular/router-deprecated": "2.0.0-rc.2",
    "@angular/upgrade": "2.0.0-rc.4",
    "bootstrap": "^3.3.6",
    "core-js": "^2.4.0",
    "primeng": "^1.0.0-beta.9",
    "primeui": "^4.1.12",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.0.0-beta.6",
    "systemjs": "0.19.27",
    "zone.js": "^0.6.12"
  },
  "devDependencies": {
    "gulp": "^3.9.1",
    "q": "^1.4.1",
    "rimraf": "^2.5.3",
    "typescript": "^1.8.10",
    "typings": "^1.0.4"
  }
}

// typings.json
{
  "globalDependencies": {
    "core-js": "registry:dt/core-js#0.0.0+20160602141332",
    "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
    "node": "registry:dt/node#6.0.0+20160621231320"
  }
}

// tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "outDir": "../wwwroot/app/"
  },
  "compileOnSave": true,
  "exclude": [
    "node_modules",
    "wwwroot"
  ]
}

// systemjs.config.js
/**
 * System configuration for Angular 2 samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
    // map tells the System loader where to look for things
    var map = {
        'app': 'app', // 'dist',
        '@angular': 'lib/@angular',
        'rxjs': 'lib/rxjs',
        'primeng': 'lib/primeng'
    };
    // packages tells the System loader how to load when no filename and/or no extension
    var packages = {
        'app': { main: 'main.js', defaultExtension: 'js' },
        'rxjs': { defaultExtension: 'js' },
        'primeng': { defaultExtension: 'js' }
    };
    var ngPackageNames = [
      'common',
      'compiler',
      'core',
      'forms',
      'http',
      'platform-browser',
      'platform-browser-dynamic',
      'router',
      'router-deprecated',
      'upgrade',
    ];
    // Individual files (~300 requests):
    function packIndex(pkgName) {
        packages['@angular/' + pkgName] = { main: 'index.js', defaultExtension: 'js' };
    }
    // Bundled (~40 requests):
    function packUmd(pkgName) {
        packages['@angular/' + pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
    }
    // Most environments should use UMD; some (Karma) need the individual index files
    var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
    // Add package entries for angular packages
    ngPackageNames.forEach(setPackageConfig);
    var config = {
        map: map,
        packages: packages
    };
    System.config(config);
})(this);

// main.ts
/// <reference path="../typings/globals/core-js/index.d.ts" />

import { bootstrap }      from '@angular/platform-browser-dynamic';
import { HTTP_PROVIDERS } from '@angular/http';

import { AppComponent }         from './components/app.component';
import { appRouterProviders }   from './app.routes';

bootstrap(AppComponent, [
    appRouterProviders,
    HTTP_PROVIDERS,
]);

// app.component.ts
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';

import './rxjs-operators';

import { PrivilegeService } from '../services/privilege.service';
import { UserService }  from '../services/user.service';

@Component({
    selector: 'my-app',
    templateUrl: "app/app.component.html",
    styleUrls: ["app/app.component.css"],
    directives: [ROUTER_DIRECTIVES],
    providers: [
        PrivilegeService,
        UserService
    ]
})
export class AppComponent {
    title = 'NG App 3.0 Future beta 0.001';
}

// users.components.ts
import { Component, OnInit } from '@angular/core';
import { Router }            from '@angular/router';

import { DataTable, Column } from '../../node_modules/primeng/primeng';

import { User }              from '../models/user';
import { UserService }       from '../services/user.service';

@Component({
    selector: 'my-users',
    templateUrl: 'app/users.component.html',
    providers: [UserService],
    directives: [DataTable, Column]
})
export class UsersComponent implements OnInit {
    users: User[];

    constructor(
        private router: Router,
        private userService: UserService) { }

    getUsers() {
        this.userService
            .getUsers()
            .then(users => this.users = users)
            .catch(error => console.log(error));
    }

    ngOnInit() {
        this.getUsers();
    }

    gotoUserDetails(event) {
        let link = ['/user', event.data.id];
        this.router.navigate(link);
    }
}

// user.service.ts (Promise)
import { Injectable }    from '@angular/core';
import { Headers, Http } from '@angular/http';
import '../rxjs-operators';

import { User } from '../models/user';

@Injectable()
export class UserService {
    private usersUrl = 'http://localhost:25153/users';

    constructor(private http: Http) { }

    getUsers(): Promise<User[]> {
        return this.http.get(this.usersUrl)
            // .toPromise() cannot be found
            .toPromise()
            .then(response => response.json())
            .catch(this.handleError);
    }

    getUser(id: string) {
        return this.getUsers()
            .then(users => users.find(user => user.id === id));
    }

    private handleError(error: any) {
        console.error('An error occurred', error);
        return Promise.reject(error.message || error);
    }
}

// privilege.service.ts (Observable)
import { Injectable }    from '@angular/core';
import { Headers, Http, Response } from '@angular/http';
import { Observable }     from 'rxjs/Observable';
import '../rxjs-operators';
import { Privilege } from '../models/privilege';

@Injectable()
export class PrivilegeService {
    private privilegesUrl = 'http://localhost:25153/privileges';

    constructor(private http: Http) { }

    getPrivileges(): Observable<Privilege[]> {
        return this.http.get(this.privilegesUrl)
            // .map() cannot be found, only .forEach(), .lift() and .subscribe() seem to be available
            .map(this.extractData)
            .catch(this.handleError);
    }

    private extractData(res: Response) {
        let body = res.json();
        return body.data || {};
    }

    getPrivilege(id: string) {
        return null;
        //return this.getPrivileges()
        //    .then(privileges => privileges.find(privilege => privilege.id === id));
    }

    private handleError(error: any) {
        console.error('An error occurred', error);
        return Promise.reject(error.message || error);
    }
}

Last but not least:

  • npm -v : 3.10.3
  • node -v : v6.3.0
  • Visual Studio 2015 Update 3

I've already deleted the folder node_modules and rebuilt it. Didn't change a bit.

Also, I've tried to build it outside of Visual Studio, but I simply have no idea how to do so. When I enter something like npm run tsc --rootDir .\\app I get the following output:

> mvc-angular-2@0.0.1 tsc C:\Users\Carsten Franke\Documents\Visual Studio 2015\Projects\MVCAngular2\src\Client
> tsc ".\app"

error TS6053: File 'app.ts' not found.

npm ERR! Windows_NT 6.3.9600
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "run" "tsc" "--rootDir" ".\\app"
npm ERR! node v6.3.0
npm ERR! npm  v3.10.3
npm ERR! code ELIFECYCLE
npm ERR! mvc-angular-2@0.0.1 tsc: `tsc ".\app"`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the mvc-angular-2@0.0.1 tsc script 'tsc ".\app"'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the mvc-angular-2 package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     tsc ".\app"
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs mvc-angular-2
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls mvc-angular-2
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     C:\Users\Carsten Franke\Documents\Visual Studio 2015\Projects\MVCAngular2\src\Client\npm-debug.log

He's perfectly right, there is no file app.ts . That is why I told him to transpile a folder. By the way, that's the file and folder structure (stripped by the node_modules' files, the .map files and some Visual Studio specific stuff):

D:\projects\MVCAngular2\src\Client\
...\app\app.routes.ts
...\app\components
...\app\components\app.component.html
...\app\components\app.component.ts
...\app\components\user-detail.component.html
...\app\components\user-detail.component.ts
...\app\components\users.component.html
...\app\components\users.component.ts
...\app\main.ts
...\app\models
...\app\models\privilege-group.ts
...\app\models\privilege.ts
...\app\models\user.ts
...\app\rxjs-operators.ts
...\app\services
...\app\services\privilege.service.ts
...\app\services\user.service.ts
...\app\tsconfig.json
...\gulpfile.js
...\node_modules\[14.536 node_modules files]
...\package.json
...\Program.cs
...\Startup.cs
...\typings
...\typings.json
...\typings\globals
...\typings\globals\core-js
...\typings\globals\core-js\index.d.ts
...\typings\globals\core-js\typings.json
...\typings\globals\jasmine
...\typings\globals\jasmine\index.d.ts
...\typings\globals\jasmine\typings.json
...\typings\globals\node
...\typings\globals\node\index.d.ts
...\typings\globals\node\typings.json
...\typings\index.d.ts
...\web.config
...\wwwroot
...\wwwroot\app
...\wwwroot\app\app.routes.js
...\wwwroot\app\components
...\wwwroot\app\components\app.component.js
...\wwwroot\app\components\user-detail.component.js
...\wwwroot\app\components\users.component.js
...\wwwroot\app\main.js
...\wwwroot\app\models
...\wwwroot\app\models\privilege-group.js
...\wwwroot\app\models\privilege.js
...\wwwroot\app\models\user.js
...\wwwroot\app\rxjs-operators.js
...\wwwroot\app\services
...\wwwroot\app\services\privilege.service.js
...\wwwroot\app\services\user.service.js
...\wwwroot\images\...
...\wwwroot\index.html
...\wwwroot\lib\[copy of node_modules]
...\wwwroot\scripts\...
...\wwwroot\styles\...
...\wwwroot\systemjs.config.js

I found this nice plnkr which uses exactly the same versions as I do and works like a charm. The only difference I see is that the scripts are transpiled in the browser.

Any ideas what's wrong?

Best regards, Carsten

Looks like you have wrong import. With your imports you've imported Observalbe object, but didn't import operators. Try to change in your service files:

import '../rxjs-operators';

to

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/catch';

or in more general way:

import 'rxjs/Rx';

The problem is, that tsc cannot compile folder. Simply. It requires a file to compile.

If you wanna compile all - you must use one of builders, like gulp - https://www.npmjs.com/package/gulp-typescript or better - webpack, I can recommend this starter - https://github.com/AngularClass/angular2-webpack-starter

I used it as a base for one of my company project's, which is now in production

Or, as alternative - smart IDEs, like WebStorm or whatever - can compile 'on-a-fly' all ts files to js

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM