[Angular 2] Understanding OpaqueToken

本文介绍了Angular中使用Opaque Tokens来避免第三方库与自定义服务之间的token冲突问题。通过实例展示了如何创建并应用Opaque Token,确保应用程序中注入的token始终唯一。

When using provider string tokens, there’s a chance they collide with other third-party tokens. Angular has with the concept of opaque tokens, that allow us to make whatever token we use unique, so we don’t run into collision problems. In this lesson we’ll explore how they work.

 

We created a value provide like this:
 providers: [
    TodoService,
    ConsoleService,
    TranslateService,
   ,{
        provide: LoggerProvider, useFactory: (cs, ts) => {
             return new LoggerProvider(cs, ts, true)
        },
        deps: [ConsoleService, TranslateService]
    } 
   ,{
        provide: apiUrl,
        useValue: 'http://localhost:3000/api'
    }
],

It turns out that this can be problematic in case we're using, for example, a third-party library that comes with its own provider that introduces the same token.

 

third-party.ts:

export const THIRD_PARTY_PRIVODERS = [
  {
      provide: apiUrl,
      useValue: 'someurl'
  }
]

 

So when you inject third-pary library into our app.ts:

 providers: [
    TodoService,
    ConsoleService,
    TranslateService,
   ,{
        provide: LoggerProvider, useFactory: (cs, ts) => {
             return new LoggerProvider(cs, ts, true)
        },
        deps: [ConsoleService, TranslateService]
    } 
   ,{
        provide: apiUrl,
        useValue: 'http://localhost:3000/api'
    }
   ,THIRD_PARTY_PROVIDERS
], 

Then it will rewrite our 'apiUrl' because THIRD_PARTY_PROVIDERS comes behind apiUrl.

 

To solve this problem, Angular introduce OpaqueToken. 

app.tokens.ts:

import {OpaqueToken} from '@angular/core';

export const API_URL = new OpaqueToken('apiUrl')

Now 'API_URL' is a class instance not just a string, class instance is always unique.

 

Then in app.ts:

import {API_URL} from './app.tokens' 

providers: [
    TodoService,
    ConsoleService,
    TranslateService,
   ,{
        provide: LoggerProvider, useFactory: (cs, ts) => {
             return new LoggerProvider(cs, ts, true)
        },
        deps: [ConsoleService, TranslateService]
    } 
   ,{
        provide: API_URL,
        useValue: 'http://localhost:3000/api'
    }
   ,THIRD_PARTY_PROVIDERS
], 

In DataService:

import {LoggerProvider} from './LoggerProvider';
import {Injectable} from '@angular/core';
import {Http} from '@angular/core';
import {Inject} from '@angular/core';
import {API_URL} from './app.tokens';

@Injectable
export class TodoService{

    constructor(@Inject(API_URL) private apiUrl, private logger: LoggerProvider, private http: Http){ }

    getTodos(){
        this.logger.debug('Items', this.todos);
        return this.http.get(`${this.apiUrl}/todos`).map(res => res.json());
    }
}

Now we won't have conflict anymore.

 

As a general rule, always create opaque tokens when using string tokens for providers. For example:

third-party.ts:

import {OpaqueToken} from '@angular/core';

const API_URL = new OpaqueToken('apiUrl');
const CONFIG_URL = new OpaqueToken('configUrl');

export const THIRD_PARTY_PROVIDERS = [
  {
     provide: API_URL,
     useValue: 'somevalue'
  },
  {
     provide: CONFIG_URL,
     useValue: 'somevalue'
  }
]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值