mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
These changes introduce the new `@Service` decorator which is a more ergonomic alternative to `@Injectable`. The reason we're adding a new decorator is that `@Injectable` has been around since the beginning of Angular and it has a lot of baggage that adds unnecessary overhead for users that generally want to define a singleton service, available in their entire app. The key differences between `@Service` and `@Injectable` are:
1. `@Service` is `providedIn: 'root'` by default. You can opt into providing the service yourself by setting `autoProvided: false` on it.
2. `@Service` doesn't allow constructor-based injection, only the `inject` function.
3. `@Service` doesn't support the complex type signature of `@Injectable` (`useClass`, `useValue` etc.). Instead it supports a single `factory` function.
Example:
```ts
import {Service} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {AuthService} from './auth';
@Service()
export class PostService {
private readonly httpClient = inject(HttpClient);
private readonly authService = inject(AuthService);
getUserPosts() {
return this.httpClient.get('/api/posts/' + this.authService.userId);
}
}
```
58 lines
1.6 KiB
TypeScript
58 lines
1.6 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.dev/license
|
|
*/
|
|
|
|
import {createInjectableType, delegateToFactory} from './injectable_compiler_2';
|
|
import * as o from './output/output_ast';
|
|
import {Identifiers} from './render3/r3_identifiers';
|
|
import {R3CompiledExpression, R3Reference} from './render3/util';
|
|
import {DefinitionMap} from './render3/view/util';
|
|
|
|
export interface R3ServiceMetadata {
|
|
name: string;
|
|
type: R3Reference;
|
|
typeArgumentCount: number;
|
|
autoProvided?: boolean;
|
|
factory?: o.Expression;
|
|
}
|
|
|
|
export function compileService(
|
|
meta: R3ServiceMetadata,
|
|
resolveForwardRefs: boolean,
|
|
): R3CompiledExpression {
|
|
const def = new DefinitionMap<{
|
|
token: o.Expression;
|
|
factory: o.Expression;
|
|
autoProvided: o.Expression;
|
|
}>();
|
|
def.set('token', meta.type.value);
|
|
def.set(
|
|
'factory',
|
|
meta.factory === undefined
|
|
? delegateToFactory(
|
|
meta.type.value as o.WrappedNodeExpr<any>,
|
|
meta.type.value as o.WrappedNodeExpr<any>,
|
|
resolveForwardRefs,
|
|
)
|
|
: o.arrowFn([], meta.factory.callFn([])),
|
|
);
|
|
|
|
// Only generate providedIn property if it's different from the default.
|
|
if (meta.autoProvided === false) {
|
|
def.set('autoProvided', o.literal(false));
|
|
}
|
|
|
|
const expression = o
|
|
.importExpr(Identifiers.defineService)
|
|
.callFn([def.toLiteralMap()], undefined, true);
|
|
|
|
return {
|
|
expression,
|
|
type: createInjectableType(meta.type.type, meta.typeArgumentCount),
|
|
statements: [],
|
|
};
|
|
}
|