-
Notifications
You must be signed in to change notification settings - Fork 1
/
NG0200.en.vtt
143 lines (108 loc) · 4.24 KB
/
NG0200.en.vtt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
WEBVTT
Kind: subtitles
Language: en
00:00.240 --> 00:04.080
Circular dependency in DI detected.
You'll encounter this error when you\h\h
00:04.080 --> 00:09.200
have a dependency that depends on itself,\h
either directly, or more often indirectly.\h
00:09.200 --> 00:13.600
A runtime error will be thrown in the browser\h
console telling you which class is effected, but\h\h
00:13.600 --> 00:18.400
what's perhaps more useful is a warning that can\h
be seen both in the console and in the terminal.\h
00:18.400 --> 00:21.760
Most importantly, it provides the\h
path of the circular dependency.\h
00:21.760 --> 00:26.960
If we look closely, it's telling us we have a\h
storage class that injects a user class, which\h\h
00:26.960 --> 00:31.520
itself depends on the original storage class.
Let's go ahead and look at a simple reproduction,\h\h
00:31.520 --> 00:35.680
and then we'll take some time to go in depth\h
about angular's dependency injection system.\h
00:35.680 --> 00:40.480
If we take a look at our source code, you'll\h
notice we have two services, user and storage.\h
00:40.480 --> 00:45.600
The problem is that user has injected storage\h
in its constructor and storage has injected\h\h
00:45.600 --> 00:49.840
user in its constructor, putting them in\h
an impossible codependent relationship.\h
00:49.840 --> 00:54.800
The solution to this problem is to break the loop,\h
which will most likely require some refactoring.\h\h
00:54.800 --> 00:59.440
It's perfectly okay for an @Injectable to depend\h
on another @Injectable, but the relationship\h\h
00:59.440 --> 01:04.640
can only go one way, which means in this case we\h
need to refactor to remove the user service from\h\h
01:04.640 --> 01:10.400
storage, or vice versa, remove the storage service\h
from user, and generally speaking, it's a good\h\h
01:10.400 --> 01:14.800
idea to minimize the number of dependencies in\h
an @Injectable service, because that will reduce\h\h
01:14.800 --> 01:20.000
the likelihood of similar issues coming up in the\h
future. Now in our storage class we have a method\h\h
01:20.000 --> 01:25.040
to write the user to the database, but it depends\h
on the user service for the current user value.\h\h
01:25.040 --> 01:30.480
We can address the problem here by refactoring\h
our code to take the user value as an argument,\h\h
01:30.480 --> 01:35.120
rather than inject the entire user class. Not only\h
does that allow us to remove the dependency from\h\h
01:35.120 --> 01:39.040
the constructor, it will also make this code\h
easier to unit test, because you don't have\h\h
01:39.040 --> 01:44.320
an additional dependency to mock or worry about,\h
and the method only depends on its input arguments\h\h
01:44.320 --> 01:49.600
making it easier to reason about. Now if we go\h
ahead and save our changes, the error is gone. But\h\h
01:49.600 --> 01:54.480
before we wrap things up, let's take a deeper look\h
at Angular's dependency injection to understand\h\h
01:54.480 --> 01:59.280
why this error happens in the first place. When\h
you generate a service with the Angular CLI you'll\h\h
01:59.280 --> 02:04.000
notice how the class is decorated with @Injectable\h
when used with the \{ providedIn: 'root' \} option,\h\h
02:04.000 --> 02:07.840
Angular will instantiate the class and make\h
it visible throughout the entire application.\h\h
02:08.400 --> 02:13.040
Unlike a component, this class is only\h
instantiated once as a singleton. Now\h\h
02:13.040 --> 02:17.760
imagine two classes that depend on each other, how\h
do you determine which one to instantiate first?\h\h
02:17.760 --> 02:21.760
It's a classic chicken or the egg paradox, and\h
that just doesn't work when you're following\h\h
02:21.760 --> 02:26.960
the dependency inversion principle. Let's go ahead\h
and recap. When you encounter circular dependency\h\h
02:26.960 --> 02:31.600
in DI detected, the first step is to determine\h
which dependencies create a loop by mapping\h\h
02:31.600 --> 02:35.680
out the dependencies and the constructor\h
of your components modules and services.\h\h
02:35.680 --> 02:40.160
Once identified you can then refactor your code\h
to break the loop. For additional details and\h\h
02:40.160 --> 02:44.720
examples check out the dependency injection\h
guide in the official Angular documentation.