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.
[00:00] In our little application, we have a provider token for the API URL, which is just a string. 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.
[00:15] To illustrate this issue, let's fake these third-party providers by quickly creating a new file in source app third-party ts, and export a constant third-party providers, which is a list of providers that this imaginary third-party library introduces.
[00:42] We add a provider for API URL and give it some other value. Basically, this is now yet another provider that happens to have the same token that we've already introduced in our application.
[00:59] Now let's go back to our list component and import third-party providers. We add them to our list of providers. Save the file, and we'll see that we run into an error.
[01:16] Our data service now tries to fetch data from a broken API URL, because the third-party library has changed the value that gets injected. This is because all providers defined on the component are flattened and normalized.
[01:29] We could get around this by changing the order of providers, so that our API URL comes last. However, this is obviously not an option. We shouldn't care in which order we define our providers. In fact, we often don't even know what tokens our third-party library introduces. There has to be a better way.
[01:51] Angular has the concept of opaque tokens, which ensure that tokens are always unique. Let's create such a unique token for our API URL and create a new file in source app tokens ts.
[02:07] Here we import opaque token from Angular Core, and export a new constant API URL, which is an instance of new opaque token for the string API URL. API URL is now an actual class instance, not just a simple string. Class instance are always unique.
[02:35] We can now go back to our list component and import API URL, and use that as a token for our provider. Last but not least, we have to make sure that the same token is used in our data service to actually inject the dependency.
[02:52] We go to our data service, import the API URL token, and pass that to @Inject. We save, reload the browser, and even though we're using a third-party library that introduces its own API URL token, we don't see the error anymore.
[03:16] This is because class instance are always unique. We can even go ahead and change the third-party to also use an opaque token. We import opaque token, create a token, and use that to register the provider.
[03:43] Our application still runs as expected. As a general rule, always create opaque tokens when using string tokens for providers.
If we change the third-party to also use an opaque token How does Angular know which 'API_URL' token to use ?
<pre><code> providers: [ DataService, ConsoleService, { provideL LogDebugger, useFactory: (consoleService) => { return new LogDebugger(consoleService, true); }, deps: [ConsoleService] }, { provide: API_URL , useValue: 'http://localhost:4200/api'; }, THIRD_PARTY_PROVIDERS ] </code></pre>This is deprecated since Angular 4. They're recommending a switch to InjectionToken.
What about using a
Symbol