正确理解angular14中的inject——inject()必须从注入上下文调用



我正在努力学习angular 14的变化,特别是inject()功能,我可以将模块注入函数,我不需要为此创建特殊的服务。但是我觉得我弄错了。

我正在尝试创建一些静态函数来使用包ngx-toastr发送零食消息,但是这个包与我的问题无关。如何正确实现显示零食消息的函数,同时向它们注入操作所需的模块。

这是我的messages.ts文件:

import {inject} from '@angular/core';
import {ToastrService} from 'ngx-toastr';

export const snackMsgSuccess = (msg: string, title?: string) => {
const toaster = inject(ToastrService);
toaster.success(msg, title, {
easeTime: 1000
});
};

export const snackMsgInfo = (msg: string, title?: string) => {
const toaster = inject(ToastrService);
toaster.info(msg, title, {
easeTime: 1000
});
};
export const snackMsgWarn = (msg: string, title?: string) => {
const toaster = inject(ToastrService);
toaster.warning(msg, title, {
easeTime: 1000
});
};

export const snackMsgError = (msg: string, title?: string) => {
const toaster = inject(ToastrService);
toaster.error(msg, title, {
easeTime: 1000
});
};

,我得到以下错误:

Error: Uncaught (in promise): Error: NG0203: inject() must be called from an injection context (a constructor, a factory function or a field initializer)

嗯…当我尝试使用支持函数来获取路由参数时,我遇到了一个问题:

export const routeParam$ = (key: string) => {
const activatedRoute = inject(ActivatedRoute);
return activatedRoute.params.pipe(
pluck(key),
filter(r => r !== null),
distinctUntilChanged()
);
};

,并且我只能在task: Observable<string> = routeParam$('task');

组件中用作字段初始化器。错误信息非常清楚…但还是. .我刚接触angular14,我想inject可以让我做到这一点。除此之外,它对我来说没什么用处。

现在我把它作为一个服务…

import {Injectable} from '@angular/core';
import {ToastrService} from 'ngx-toastr';
@Injectable({
providedIn: 'root'
})
export class MsgService {
constructor(private toaster: ToastrService) {
}
public snackMsgSuccess = (msg: string, title?: string) => {
this.toaster.success(msg, title, {
easeTime: 1000
});
};

public snackMsgInfo = (msg: string, title?: string) => {
this.toaster.info(msg, title, {
easeTime: 1000
});
};
public snackMsgWarn = (msg: string, title?: string) => {
this.toaster.warning(msg, title, {
easeTime: 1000
});
};

public snackMsgError = (msg: string, title?: string) => {
this.toaster.error(msg, title, {
easeTime: 1000
});
};
}

但这是实现它的唯一方法吗?

正如在回答中提到的,它只能在依赖依赖的实例化过程中被初始化。您可以通过创建高阶函数来解决这个问题。

export const snackMsgSuccess = () => {
const toaster = inject(ToastrService);
return (msg: string,title?: string)=>{
toaster.success(msg, title, {
easeTime: 1000
});
}
};

component.ts

snackMsgSuccess = snackMsgSuccess();

ngOnInit(){
this.snackMsgSuccess('Success','Test');
}

更新Angular 14.1

在这个版本中,inject函数可以在函数体中使用runInContext API。

查看更多信息

从Angular 14.1开始,你可以使用runInContext:

简单的例子:

class Foo {
constructor(private injector: EnvironmentInjector) {
setTimeout(() => {
// can't inject()
this.injector.runInContext(() => {
inject(MyService) // fine
});
}, 1000);
}
}

在v16+使用runInInjectionContext

injector = inject(EnvironmentInjector);

constructor(private injector: EnvironmentInjector)

runInInjectionContext(this.injector, snackMsgSuccess);

我在一个使用Nx和Angular 15的Angular项目中也遇到了同样的问题,但没有违反这条规则。我解决了在tsconfig.base.json文件中添加以下行compilerOptions.paths:

"@angular/*": ["node_modules/@angular/*"]

最新更新