angular2将服务注入其他 - 使用@Inject

时间:2016-01-06 03:52:42

标签: dependency-injection angular angular2-services

我正在使用angular2 Beta。使用@Inject注释将DI我的一项服务转移到另一项服务时出错,无法弄清楚我错在哪里。似乎所有东西都符合Angular2 documentation

我正在使用基于云的数据服务 - CloudDB - 来满足我的应用程序的数据需求。 CloudDB为我提供了一个基于javascript的客户端库,我可以将其包含在我的js应用程序中,用于在我的cloudDB数据库中执行CRUD操作,或者调用我存储在我的CloudDB帐户中的其他自定义API,例如UserAuth API(用于验证用户凭据的API)。 在使用cloudDB js客户端lib API之前,我需要通过调用CloudDB js对象的getClient方法来提供我的cloudDB帐户的URL和authKey。

在我的angualar2应用程序中,我创建了一个可注入的服务类 - CloudDBProvider - 它将存储我的CloudDB帐户URL和authKey,并调用CloudDB.getClient来为我的CloudDB帐户设置提供者的js客户端对象。

import {Injectable} from 'angular2/angular2'; 
///<reference path="../typeDefs/CloudDB.d.ts" /> //typedef of CloudDB js library

@Injectable()
export class CloudDBProvider {
    private cloudDBClient: CloudDB.JSClient; 
    public get cloudDBClient(): CloudDB.JSClient {
        return this.cloudDBClient;
    }


    constructor() {
        this.cloudDBClient = new CloudDB.getClient(
            "https://myaccount.CloudDB.com/",
            "AcfdsfmyDdCMHeadfsdsdfHdsf68" // account authKey
        );
    }
}

现在,我想在这个angular2应用程序中创建一个UserUtils服务,我想在其上面注入以获取cloudDBClient对象。我从下面编写了UserUtils服务类,如从教程

中学到的那样
import {Injectable, Inject} from 'angular2/angular2';
import {CloudDBProvider} from './CloudDBProvider';

@Injectable()
export class UserUtils {
private _userDetails: Object = {};
private _cloudDBProvider: CloudDBProvider;
private _cloudDBClient: Microsoft.WindowsAzure.MobileServiceClient;;

constructor( @Inject(CloudDBProvider) cloudDBPrvdr: CloudDBProvider) {
    this._cloudDBProvider = cloudDBPrvdr;
    this._cloudDBClient = this._cloudDBProvider.cloudDBClient;  //the public getter property in the class CloudDBProvider
}

public authenicateUser(p_strUserName: string, p_strUserPassword: string) {
    var p: Promise<any> = new Promise(
        (resolve: (result: any) => void, reject: (err: any) => void) =>
            this._cloudDBClient.userlogin(p_strUserName, p_strUserPassword).done( //using API 'userlogin' of cloudDB to authenticate user against my cloudDB's users table.
                (loginResult) => {
                    alert("from Userutils - You are now logged in as: " + loginResult.user.basicProfile.firstName);
                    resolve(loginResult);
                },
                (loginErr: any) => {
                    alert("Error: " + loginErr.request.responseText);
                    reject(loginErr);
                }
            )
    );

    return p;
}

}

然后我尝试在我的LoginPage组件中使用UserUtils,如下所示:

import {Component} from 'angular2/core';
import {WelcomePage} from  "../views/welcome/welcome";
import {UserUtils} from  "../services/UserUtils";


@Component({
    templateUrl: 'app/login/login.html',
    providers: [UserUtils]
})
export class LoginPage {
    private _userUtils: UserUtils;

    constructor( userUtils: UserUtils) {
        this._userUtils = userUtils;
     } 


    public loginButtonClicked(event, userName, password) { //called when Login Button is clicked by user
         //...
        //... to-do field value verification 
        //...

        this._userUtils.authenicateUser(userName, password).then(
          (result) => {
              //navigate to WelcomePage
          },
           (err) => { alert(err); }

      );

   }
} 

当我使用UserUtils时,组件LoginPage不起作用。浏览器控制台抛出错误 - 没有CloudDBProvider的提供程序! (LoginPage - &gt; UserUtils - &gt; CloudDBProvider)

请注意,如果我将'authenicateUser'方法从UserUtils直接移动到CloudDBProvider并在LoginPage组件中使用CloudDBProvider进行用户身份验证,那么一切正常,用户获得身份验证并在登录后导航到欢迎页面。此外,如果我从UserUtils的构造函数中删除@Inject(CloudDBProvider)cloudDBPrvdr,则不会抛出任何错误并且app工作显然我不能在UserUtils中使用CloudDBProvider,但是点app是不会抛出任何错误,这意味着@Inject有问题。

我出错的任何线索?

2 个答案:

答案 0 :(得分:1)

根据我的理解你的错误在于导入会改变Injectable的导入

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

当我们使用@injectable注释时,也不需要在构造函数中使用@inject,只需将服务与public标识符放在一起,就可以将该服务用于任何其他服务同一类的方法。

答案 1 :(得分:0)

也许您可以在组件的提供商列表中添加class MedianBestChart { JFreeChart chart; ChartComposite innerChartComposite; java.awt.Color awtRedColor; Shape downTriangleShap; Shape upTriangleShape; XYPlot plot; XYLineAndShapeRenderer renderer; XYSeries bestValsSeries; XYSeries medianValsSeries; XYSeries diffValsSeries; XYSeriesCollection dataset; MedianBestChart(String title, String yAxisText) { this.bestValsSeries = new XYSeries("Best candidate"); this.medianValsSeries = new XYSeries("Median"); this.diffValsSeries = new XYSeries("Diff"); this.dataset = new XYSeriesCollection(); this.dataset.addSeries(this.bestValsSeries); this.dataset.addSeries(this.medianValsSeries); this.dataset.addSeries(this.diffValsSeries); this.awtRedColor = SWTUtils.toAwtColor(SWTResourceManager .getColor(SWT.COLOR_RED)); this.downTriangleShap = ShapeUtilities.createDownTriangle(3); this.upTriangleShape = ShapeUtilities.createUpTriangle(3); this.chart = createChart(title, yAxisText); this.innerChartComposite = new ChartComposite( CloudDeploymentOptionsCreationWizardPage3ACO.this.chartParentComposite, SWT.FILL, this.chart, true); // grid data for the composite; final GridData chartCompositeGridData = new GridData(SWT.FILL, // horizontalAlignment; SWT.FILL, // verticalAlignment; true, // grabExcessHorizontalSpace; true); // grabExcessVerticalSpace; chartCompositeGridData.grabExcessHorizontalSpace = true; chartCompositeGridData.grabExcessVerticalSpace = true; this.innerChartComposite.setLayoutData(chartCompositeGridData); this.innerChartComposite.setRangeZoomable(false); this.innerChartComposite.setDomainZoomable(false); this.innerChartComposite.setVisible(true); this.chart.setBorderVisible(false); CloudDeploymentOptionsCreationWizardPage3ACO.this.chartParentComposite .layout(true); } JFreeChart createChart(String title, String yAxisText) { // create the chart... final JFreeChart chart = ChartFactory.createXYLineChart(title, "Nr. candidates", // x // axis // label yAxisText, // y axis label this.dataset, // data PlotOrientation.VERTICAL, true, // include legend false, // tooltips false // urls ); chart.setBackgroundPaint(SWTUtils.toAwtColor(Display.getDefault() .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND))); Font titleFontTmp = chart.getTitle().getFont(); Font chartTitleFont = new Font("Plot title font", titleFontTmp.getStyle(), titleFontTmp.getSize() - 6); chart.getTitle().setFont(chartTitleFont); this.plot = chart.getXYPlot(); this.plot.setBackgroundPaint(java.awt.Color.white); this.plot.setDomainGridlinePaint(java.awt.Color.LIGHT_GRAY); this.plot.setRangeGridlinePaint(java.awt.Color.LIGHT_GRAY); this.renderer = new XYLineAndShapeRenderer(true, true) { private static final long serialVersionUID = 8963966491796723264L; @Override public LegendItem getLegendItem(int datasetIndex, int series) { if (series != 2) { return super.getLegendItem(datasetIndex, series); } else { return null; } } }; this.renderer.setSeriesLinesVisible(0, true); this.renderer.setSeriesShapesVisible(0, false); this.renderer.setSeriesPaint(0, java.awt.Color.blue); this.renderer.setSeriesLinesVisible(1, true); this.renderer.setSeriesShapesVisible(1, false); this.renderer.setSeriesPaint(1, new java.awt.Color(210, 105, 30)); this.renderer.setSeriesStroke(2, new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f, new float[] { 2.0f, 6.0f }, 0.0f)); this.plot.setRenderer(this.renderer); final NumberAxis domainAxis = (NumberAxis) this.plot .getDomainAxis(); domainAxis .setStandardTickUnits(NumberAxis.createIntegerTickUnits()); final NumberAxis rangeAxis = (NumberAxis) this.plot.getRangeAxis(); rangeAxis.setNumberFormatOverride(NumberFormat .getInstance(Locale.US)); return chart; } XYSeries getXYSeries(List<Double> vals, XYSeries series) { series.clear(); for (int i = 0; i < vals.size(); ++i) { series.add(i + 1, vals.get(i)); } return series; } void updateChart(List<Double> bestVals, List<Double> medianVals) { int size = bestVals.size(); this.bestValsSeries = getXYSeries(bestVals, this.bestValsSeries); this.medianValsSeries = getXYSeries(medianVals, this.medianValsSeries); this.diffValsSeries.clear(); if (size > 1) { this.diffValsSeries.add(size, bestVals.get(size - 1)); this.diffValsSeries.add(size, medianVals.get(size - 1)); } this.renderer.setSeriesPaint(2, java.awt.Color.green); this.renderer.setSeriesShape(2, this.upTriangleShape); if (this.dataset.getItemCount(0) > 0) { if (betterThanMedian(this.dataset.getSeries(0), this.dataset.getSeries(1), false)) { this.renderer.setSeriesPaint(2, java.awt.Color.red); this.renderer.setSeriesShape(2, this.downTriangleShap); } } // Refresh chart this.plot.setDataset(this.dataset); } } private Label lblLcloudenvironmentval; private Label lblVMsAtStartVal; private Label reconfigRulesVal; private Label lCostVal; private Label lCostBetterThanVal; private Label lMedianResponseTimesVal; private Label lMedianResponseTimesBetterThanVal; private Label lTimeoutsVal; private Label lTimeoutsBetterThanVal; private ProgressBar currentCDOprogressBar; private ProgressBar overallProgressBar; private boolean optimizationStarted; private CDOCreationOptimizedAutomaticMethod cdoCreationJob; private boolean saveBestFoundCDO; private Label lblRunning; private Label lblSimulatedCandidates; private Label lRunningVal; private Label lSimulatedCandidatesVal; private Date optimizationStartedDate; private Group grpBestFoundCandidate; private Label lblCurrentCloudDeployment; private Label lblOverallProgress; private Button btnDetailsBestCDO; private final Color swtBlackColor; private final Color swtGreenColor; private final Color swtRedColor; private MedianBestChart costChart; private MedianBestChart responseTimeChart; private MedianBestChart slaViolationsChart; private final Job elapsedTimeUpdaterJob = new Job( "Elapsed Time Updater Job") { private volatile boolean cancel = false; @Override protected void canceling() { this.cancel = true; } @Override protected IStatus run( IProgressMonitor arg0) { while (true) { Display.getDefault() .asyncExec( new Runnable() { @Override public void run() { CloudDeploymentOptionsCreationWizardPage3ACO.this.lRunningVal .setText(Utilities .getElapsedTime(CloudDeploymentOptionsCreationWizardPage3ACO.this.optimizationStartedDate)); } }); try { getThread(); Thread.sleep(1000); if (this.cancel) { return Status.OK_STATUS; } } catch (InterruptedException e) { Utilities .logError(e .getMessage()); } } } }; private Composite chartParentComposite; private final AbstractHandler updateChartsHandler = new AbstractHandler() { @Override public Object execute( ExecutionEvent ee) throws ExecutionException { Map<String, Pair<List<Double>, List<Double>>> applicationContext = (Map<String, Pair<List<Double>, List<Double>>>) ee .getApplicationContext(); final Pair<List<Double>, List<Double>> costsBestAndMedianVals = applicationContext .get(org.cloudmig.cloudmigxpress.activity.generation.transformation.ga.Messages.CDOEvaluator_lowCostObjective); final Pair<List<Double>, List<Double>> responseTimesBestAndMedianVals = applicationContext .get(org.cloudmig.cloudmigxpress.activity.generation.transformation.ga.Messages.CDOEvaluator_lowResponseTimesObjective); final Pair<List<Double>, List<Double>> nrTimeoutsBestAndMedianVals = applicationContext .get(org.cloudmig.cloudmigxpress.activity.generation.transformation.ga.Messages.CDOEvaluator_lowNrSLAViolationsObjective); Display.getDefault() .asyncExec( new Runnable() { @Override public void run() { updateCharts( costsBestAndMedianVals, responseTimesBestAndMedianVals, nrTimeoutsBestAndMedianVals); } }); return null; } }; /** * Create the wizard. */ public CloudDeploymentOptionsCreationWizardPage3ACO() { super("wizardPage"); setImageDescriptor(ResourceManager .getPluginImageDescriptor("org.cloudmig.cloudmigxpress", "icons/iconfinder_com_1327065738_question-type-one-correct.png")); setTitle("Compute Best Suited Cloud Deployment Option"); setDescription("Step 3 of 3 - Run the cloud deployment optimization process"); this.optimizationStarted = false; this.saveBestFoundCDO = true; this.swtBlackColor = SWTResourceManager.getColor(SWT.COLOR_BLACK); this.swtGreenColor = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); this.swtRedColor = SWTResourceManager.getColor(SWT.COLOR_RED); } 提供商:

CloudDBProvider

或者在@Component({ templateUrl: 'app/login/login.html', providers: [UserUtils, CloudDBProvider] }) export class LoginPage { (...) } 函数的第二个参数中的应用程序级别:

bootstrap

这个答案可以给你一些额外的提示:Angular2 Beta dependency injection

希望它可以帮到你, 亨利