我正在使用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有问题。
我出错的任何线索?
答案 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。
希望它可以帮到你, 亨利