Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranรฎ)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
1 1
Many real world applications 2
2
have two special modules that are completely independent 3
3
of the rest of the architecture. 4
4
And these are a module for the project configuration 5
5
and also a module for some general helper functions 6
6
that are gonna be useful across the entire project. 7
7
And so let's now implement these modules in our own project. 8
8
And let's start with the configuration module. 9
9
So let's maybe close this one here first. 10
10
And then in our JS folder, 11
11
we create a new file 12
12
config.js. 13
13
Okay. 14
14
And so here into this file, 15
15
we will basically put all the variables 16
16
that should be constants 17
17
and should be reused across the project. 18
18
And the goal of having this file with all these variables 19
19
is that it will allow us to easily configure 20
20
or project by simply changing some of the data 21
21
that is here in this configuration file. 22
22
So therefore the name of config. 23
23
So of course we will not want to put all the variables 24
24
here in this file. 25
25
The only variables that we do want here 26
26
are the ones that are responsible 27
27
for kind of defining some important data 28
28
about the application itself. 29
29
So one example of that is for example, 30
30
the API URL. 31
31
All right. 32
32
So this URL here, we will actually reuse in multiple places 33
33
across this project, for example, for getting search data, 34
34
and also for uploading a recipe to the server. 35
35
And so all of them will use this URL. 36
36
But then imagine that at some point the URL needs to change. 37
37
For example, 38
38
because there might be a version 3 at some point. 39
39
And so as always, we don't want to change that everywhere 40
40
and simply have a variable which contains this 41
41
which we can then reuse. 42
42
So let's cut this here 43
43
and you might argue that we can 44
44
also simply create a variable here in the model, 45
45
but then we would have all these configuration variables 46
46
spread across multiple modules, 47
47
but it's way easier to simply have all of those variables 48
48
in one central place. 49
49
And so that's what we're going to do here. 50
50
So let's call this one API URL, 51
51
and then paste that here. 52
52
Okay. 53
53
And now all we have to do 54
54
is to export this constant from here. 55
55
So, I'm using uppercase here, 56
56
because this is basically a constant that will never change. 57
57
And so using uppercase for that kind of variable 58
58
is kind of a common practice 59
59
especially in a configuration file like this. 60
60
So, API URL is one of the variables 61
61
that makes a lot of sense. 62
62
And let's actually go to our documentation page 63
63
because indeed, as I mentioned before, 64
64
we are going to use this URL for this 65
65
and also for getting recipes. 66
66
So then we will simply have to add the slash ID. 67
67
Another great candidate for being a configuration variable 68
68
is going to be this API key 69
69
that we will generate a bit later. 70
70
So let's leave that for now 71
71
and go back here to this API URL. 72
72
And now actually import that here into the model. 73
73
So import, and now remember that here 74
74
we have a named import, 75
75
and later we will actually also have more named imports. 76
76
Okay. 77
77
And so here I could go ahead 78
78
and import all of them basically at the same time 79
79
and then as config, 80
80
but actually I prefer to import them one by one, 81
81
basically with their actual name. 82
82
And so remember we do that by using curly braces 83
83
and then the name 84
84
of the variable like this, 85
85
and then config is in the same folder. 86
86
And so that should work, 87
87
and here, all we have to do now is to replace, 88
88
or to actually put that API URL 89
89
right here. 90
90
So, if we save this now, then our application, 91
91
well, let's see. 92
92
And yeah, it is back to working. 93
93
Right? 94
94
And so we successfully basically export it, 95
95
this configuration value that we had here 96
96
into this config file. 97
97
Okay. 98
98
Next up, let's create a new file for some helper functions. 99
99
So this one is usually called helpers.js. 100
100
And the goal of this file or of this module 101
101
is to contain a couple of functions 102
102
that we reuse over and over in our project. 103
103
And so here in this module 104
104
we then have a central place for all of them basically. 105
105
And to start one great candidate, 106
106
is to actually create a function which will get JSON. 107
107
So basically a function which encapsulates all of this, 108
108
and also some of the error handling. 109
109
Alright, so let's actually get all of this code 110
110
and go here into the helpers. 111
111
And so here let's create a function 112
112
and export it, called getJSON. 113
113
And so this function is going to be very similar 114
114
to what we did in the async JavaScript section. 115
115
So it's gonna be an async function 116
116
which will basically do the fetching 117
117
and also converting to JSON all in one step. 118
118
And so with this, 119
119
we abstract all this functionality into one nice function 120
120
that we can then use all over our project. 121
121
And probably, we will just use this actually in our model 122
122
in this case, but it's still good to have this function 123
123
in this kind of central place. 124
124
Okay. 125
125
So anyway, this getJSON function, we'll take a URL, 126
126
and so of course, this is then what we fetch here. 127
127
Right. 128
128
And so with this, we can then reuse this function here 129
129
for all kinds of your URLs. 130
130
Now this here actually already makes sense. 131
131
And this one here as well. 132
132
So let's now put all of this into a try block, 133
133
and then catch the error here. 134
134
Now, what are we going to do with the error here? 135
135
Of course we could log it 136
136
or alert it as always to the console 137
137
but let's say we actually want to handle that error here 138
138
in this function. 139
139
So right here where we will actually use the getJSON method. 140
140
And actually let's do that right away. 141
141
So, import that first of course, 142
142
so import, and again, we are using named imports 143
143
and I simply want to import the exact variable name. 144
144
So that's getJSON 145
145
from 146
146
helpers and it's not appearing here. 147
147
And I just noticed 148
148
that helpers is actually in the wrong folder. 149
149
So I put it in a views folder, 150
150
but it's supposed to be in the JS folder. 151
151
Okay. 152
152
And so let's now actually use getJSON here, 153
153
and then think about the error handling 154
154
that we were just talking about previously. 155
155
So here let's say constant data 156
156
will be a white 157
157
getJSON and then with this same URL here. 158
158
Okay. 159
159
And so again, this is exactly what we had done before. 160
160
There is just one thing missing here. 161
161
Now we get these errors, which is really annoying 162
162
but anyway, there's actually still something missing here, 163
163
which is to then actually return the data 164
164
from this function. 165
165
Right? 166
166
So we didn't do that yet. 167
167
And so of course we want to return the data. 168
168
And now just as we did also in the last video, 169
169
we have one async function here. 170
170
So the load recipe function calling another async function 171
171
which is this, getJSON function. 172
172
Now this function returns this data variable. 173
173
And so therefore this data is going to be the resolved value 174
174
of the promise that the getJSON function returns. 175
175
And if that's still sounds super confusing, 176
176
then you might just revisit that lecture 177
177
in the asynchronous JavaScript section. 178
178
But, anyway what you need to keep in mind is that here 179
179
this data will become the resolved value of this promise. 180
180
And so here, that's why we then await that promise 181
181
and store that resolved value into the data variable. 182
182
And so then the rest here is going to work in the same way. 183
183
But now back to error handling, 184
184
and let's say here we want to actually not alert, 185
185
but to log that error to the console, 186
186
let's say console.error. 187
187
And then here the error, and let's say, we want to do it 188
188
in a special way, just so we see which errors are our own. 189
189
So using some emoji here should make it really visible. 190
190
So this this the CLO temporary error handling 191
191
which we will improve dramatically 192
192
in one of the next lectures. 193
193
But anyway, the point that I'm trying to make 194
194
is that the error is actually occurring here, right? 195
195
It is going to occur in the getJSON function and not here. 196
196
Remember that. 197
197
So, when there's going to be an error here in this function, 198
198
then the promise that the getJSON function returns 199
199
is actually still being fulfilled. 200
200
So it's still basically a successful promise 201
201
even if there happened an error here. 202
202
And so let me show that to you actually. 203
203
So, now everything works just fine 204
204
but let's now use some invalid URL here. 205
205
Then we get some error here 206
206
but that's not the one we are interested in. 207
207
So the actual error is this one here and it's coming now 208
208
from helpers.js at line five, 209
209
or actually line 11. 210
210
So this is the error that we're logging right here. 211
211
So this one here, right? 212
212
So we're logging it to the console here, 213
213
right in the helpers function. 214
214
However, this is actually not 215
215
where we want to handle that error. 216
216
We really would like to handle it 217
217
right here in model.js. 218
218
So basically instead of this error message here, 219
219
which is simply a consequence of this first error, 220
220
we would like to get this error message inside of the model. 221
221
Right? 222
222
So do you remember how we do that? 223
223
Well, we have to re-throw the error. 224
224
So we have to again use throw, 225
225
and then simply take the error object 226
226
that we already have and simply throw this new error. 227
227
And so now with this, the promise that's being returned 228
228
from getJSON will actually reject. 229
229
Okay. 230
230
And so then we will be able 231
231
to actually handle the error right here. 232
232
So let's try that again. 233
233
And indeed now we get that same error message 234
234
that we had before right here in the model as we want it. 235
235
Okay. 236
236
So we basically propagated the error down 237
237
from one async function to the other 238
238
by re-throwing the error here in this catch block. 239
239
And that's really important to do. 240
240
And we will actually come back to this 241
241
in one of the future lectures. 242
242
Okay. 243
243
And now to finish, 244
244
let's make this function here a little bit more robust 245
245
and more real world by adding some time out. 246
246
So basically setting a time 247
247
after which we make the request fail. 248
248
And so this is important in order to prevent 249
249
for really bad internet connections 250
250
where then this fetch here could be running forever. 251
251
And we actually already did that previously 252
252
in the async JavaScript section. 253
253
And so here in the controller, stagger code, 254
254
I had already this timeout function. 255
255
So we don't have to code it all over again. 256
256
And so let's put that here. 257
257
And so basically what this function does, 258
258
is that it will return a new promise. 259
259
So this promise here, 260
260
which will reject after a certain number of seconds. 261
261
And so in order to now use this function here, 262
262
we will have a race between this time out promise 263
263
which will take whatever seconds we pass into it, 264
264
and this fetch function here, 265
265
which is the one responsible for getting the data. 266
266
And then whatever occurs first will win the race. 267
267
So let me just put that in code actually. 268
268
So, remember that works by using Promise.race, 269
269
and this takes in two promises. 270
270
So the first promise is this one, 271
271
and then the second promise will be time out 272
272
with a certain number of seconds. 273
273
And here for now, let's just say 10 seconds, 274
274
or actually let's just say, 275
275
0.5 seconds 276
276
so that we can actually test this. 277
277
So here we're still getting some errors from somewhere 278
278
in our code because of this error, 279
279
but nevermind. 280
280
Oh, and now Google Chrome crashed and here we are back. 281
281
So let's just again, click somewhere here. 282
282
Now we still got this weird error. 283
283
So let's actually check out what's happening here 284
284
with cannot read property json of undefined. 285
285
While maybe it's already because of this timeout here. 286
286
So let's try to put it to like five seconds. 287
287
Let's try it again, 288
288
but it's gotta be something else. 289
289
So it seems like there's some problem somewhere here. 290
290
So here, for some reason it's this parenthesis 291
291
which doesn't make any sense, 292
292
but it is via code, 293
293
which for some reason puts it there for us. 294
294
But this parenthesis doesn't make any sense 295
295
because now this looks like just one element of this array. 296
296
So lets just create this promise outside. 297
297
So fetch promise is going to be this. 298
298
And so hopefully that will fix it. 299
299
Well, it doesn't. 300
300
Oh, but I see what's the problem. 301
301
I'm actually not even calling promise.race. 302
302
I only put the records there. 303
303
So that was probably the reason. 304
304
And so now it should work indeed. 305
305
And So if we reload this, then yeah, it works. 306
306
So now we can actually test 307
307
what's happening here with the time. 308
308
So sending it to over a second. 309
309
And so that still works. 310
310
And so that's make our network a little bit slower. 311
311
So I slow 3G and this should then take some time. 312
312
And so let's see if we can now time out the request. 313
313
So let's wait for it. 314
314
And indeed, 315
315
now the request took too long time out after half a second. 316
316
Okay. 317
317
So let's analyze what happened here. 318
318
So we passed in half a second here. 319
319
And so after that time has passed, 320
320
this promise simply rejected with this error message. 321
321
And so as soon as any of these promises here 322
322
in the race rejects or fulfills, 323
323
then that promise will become the winner. 324
324
And so therefore we now have a rejected promise here, 325
325
which will then trigger the catch block here. 326
326
And so that error will then be thrown again here. 327
327
And then it will make its way here 328
328
into the load recipe function 329
329
and eventually will be handled down here. 330
330
And so that's why we get these four 331
331
explosions down here in the error message. 332
332
All right. 333
333
Now of course, 334
334
then in the real world, we will want to do something 335
335
with that error, but again, 336
336
a bit more on actual error handling 337
337
a bit later in the section. 338
338
For now, let's set a more realistic value here. 339
339
So of course we don't want to timeout 340
340
after just half a second. 341
341
Let's say like 10 seconds. 342
342
Now, in fact, this is one of these 343
343
so called magic numbers or magic values, 344
344
which is like a value that seems to appear out of nowhere. 345
345
So if someone reads this code, they will find this number 10 346
346
and not really understand what it's doing. 347
347
And so one more time, 348
348
this is a perfect candidate for a configuration value. 349
349
So this is really something 350
350
that we might want to change about our application. 351
351
And so then, if we want to do that, 352
352
all we have to do is to come to our config file 353
353
and change that here. 354
354
So lets call this one time out seconds 355
355
and set it to 10. 356
356
Okay. 357
357
Then here we can import that. 358
358
So again is a named import. 359
359
And so here we use the curly braces. 360
360
So a timeout seconds from 361
361
helpers.js. 362
362
And this import that is already here 363
363
was probably put here by a parcel. 364
364
So I don't remember doing this here. 365
365
And so it must have been parcel who put us here 366
366
in order to make the code work. 367
367
Okay. 368
368
And so now here we can use the time out second constant. 369
369
And so now, whoever is going to read this code 370
370
will see that this is one of the configuration values. 371
371
So, first because it is in this upper case. 372
372
And so that helps already with understanding the code. 373
373
And then also because now it is a variable. 374
374
And so it's no longer like a magic number 375
375
that we don't really understand where it's coming from. 376
376
Okay. 377
377
And so that's exactly 378
378
what this configuration file here is all about. 379
379
So, these are two important files 380
380
that are used in many applications in the real world. 381
381
And so make sure to also include them 382
382
in some way in your own applications, in the future. 383
383
Okay. 384
384
And now in the next video, 385
385
we will kind of finish this architecture 386
386
and to really implement a missing part here 387
387
which is kind of handling the events in a better way. 388
388
And so let's go do that right now.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.