How to pass parameters for dependency while Inject

2019-06-17 04:03发布

问题:

I'm making a sample application to make connection to a websocket server in ionic 2 in typescript. link to repo

My requirement is to make the websocket connection during application start up

I'm using angular2-websocket to creating the connection.

References :

  1. http://blog.thoughtram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html

  2. http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html

I'm getting a error " Cannot resolve all parameters for '$WebSocket'(String, Array, ?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that '$WebSocket' is decorated with Injectable. "

CODE: app.ts

import {App, Platform} from 'ionic-framework/ionic';
import {TabsPage} from './pages/tabs/tabs';
import {ConnectionService} from './framework/connection/connection-service'
import {$WebSocket} from 'angular2-websocket/angular2-websocket';
import {bootstrap} from 'angular2/platform/browser';

// https://angular.io/docs/ts/latest/api/core/Type-interface.html
import {Type} from 'angular2/core';


@App({
  template: '<ion-nav [root]="rootPage"></ion-nav>',
  config: {}
})
export class MyApp {
  rootPage: Type = TabsPage;

  constructor(platform: Platform, private conn : ConnectionService) {
    platform.ready().then(() => {
      this.conn.connect();
    });
  }
}
bootstrap(MyApp, [$WebSocket, ConnectionService]);

connection-service.ts

import {Injectable, Component, Inject} from 'angular2/core';
import {$WebSocket} from 'angular2-websocket/angular2-websocket';
import {bootstrap} from 'angular2/platform/browser';

@Injectable()
export class ConnectionService {

    private _status: number;

    //private connection: $WebSocket;

    constructor( private connection : $WebSocket = new $WebSocket("ws://echo.websocket.org") ) {

    console.log("Starting connection");

   //this.connection = new $WebSocket("ws://echo.websocket.org");

    this.connection.onClose(this.onCloseHandler);
    this.connection.onError(this.onErrorHandler);
    this.connection.onOpen(this.onOpenHandler);
    this.connection.onMessage(this.onRecieveHandler, {});

}
...
public connect() {
    this.connection.connect(true);
}
...
}
bootstrap(ConnectionService, [$WebSocket]);

回答1:

The Solution to my problem was using @App() Annotation's (Specific to ionic) provider field instead of using bootstrap

bootstrap(ConnectionService, 
    [provide($WebSocket, useValue: new WebSocket("ws://echo.websocket.org")]);

Eg.

@App({
  template: '<ion-nav [root]="rootPage"></ion-nav>',
  config: {},
  providers : [ provide( $WebSocket, { useValue: new $WebSocket("ws://echo.websocket.org") }), ConnectionService]
})

Working sample can be found here



回答2:

Obviously the $WebSocket requires a string, array and another parameter which makes $WebSocket not injectable, at least not directly.

As a workaround you can use

import {Injectable, Component, Inject, provide} from 'angular2/core';

bootstrap(ConnectionService, 
    [provide( $WebSocket, { useValue: new $WebSocket("ws://echo.websocket.org") })]);

There are other options if the string literal is not what you want, like a factory.



回答3:

From what I see, you should provide $WebSocket by injection since you instantiate it by your own for your service. I would remove it from bootstrap and instantiate it in the constructor instead of providing it from constructor parameters:

@Injectable()
export class ConnectionService {
  private _status: number;
  private connection: $WebSocket;

  constructor() {
    this.connection = new $WebSocket("ws://echo.websocket.org");
  }
}

That said, in general, if you want to leverage dependency injection in Angular, you must let Angular2 instantiate by itself things you want to inject in the constructor.

In your case, Angular2 tries to instantiate your $WebSocket service. I think that its constructor accepts three parameters and when Angular2 tries to resolve these parameters at instantiation level. It can't resolve the last one. Could you provide the parameters of the $WebService constructor?