diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..dfe07704 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/package-lock.json b/package-lock.json index 3513028a..f1e5e10f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6245,7 +6245,8 @@ }, "ini": { "version": "1.3.5", - "resolved": "", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, "inquirer": { diff --git a/src/app/about/about.component.ts b/src/app/about/about.component.ts index 6bf01d19..af772210 100644 --- a/src/app/about/about.component.ts +++ b/src/app/about/about.component.ts @@ -25,16 +25,8 @@ import {createHttpObservable} from '../common/util'; }) export class AboutComponent implements OnInit { - ngOnInit() { - - - } + ngOnInit() { + } } - - - - - - diff --git a/src/app/course-dialog/course-dialog.component.ts b/src/app/course-dialog/course-dialog.component.ts index 6d3017fa..215763b8 100644 --- a/src/app/course-dialog/course-dialog.component.ts +++ b/src/app/course-dialog/course-dialog.component.ts @@ -40,10 +40,94 @@ export class CourseDialogComponent implements AfterViewInit { } - ngAfterViewInit() { + /** + * we are going to show that Merge is ideal for performing + * HTTP requests in parallel, as we have seen before, + * use of concat map here is ensuring that our first + * course save is going to be completed before issuing + * the second one. + * This is the logic that we want here for save operations. + * ngOnInit() { + this.form.valueChanges + .pipe( + filter(() => this.form.valid), + concatMap(changes => this.saveCourse(changes)) + ) + .subscribe(); + } + * But if you find yourself in a situation where you would + * like to perform multiple calls to your backend in parallel + * and fetch the results of each call as they arrive over time, + * then in that case you canstill use here the merge map operator. + */ + + /** + * Merge map is very similar to concat map that we already covered. + * The principle is the same. We are going to take the values + * of the source observable and we are going to apply a mapping + * function that is going to take the value and it's going to + * produce a new observable. So here the value one was taken + * and by running this function here, we have created here a + * new observable which takes the value multiply it by ten + * and then terminates the observable, + * the observable gets completed. + * + */ + + + /** + * So remember before we were using concat map so the save + * operations would all work sequentially. + * We will have to wait for the save to complete in order to + * proceed and perform the next save. + * If instead of concat map we use merge map, + * the behavior is going to be different. + * Let's switch over here to a larger window and tried to issue + * several saves. + * In parallel, we are here on the network, so let's now type + * in here title over the course so that we can emit multiple + * observables. + * As you can see here in the waterfall diagram, + * we have several requests running in parallel. + * At the same time, we are not waiting for one request to + * complete before launching another. + * So the merge map operator is ideal for performing HTTP requests + * in parallel. + * However, in the concrete scenario of a save, we want + * really to make sure that the save is completed + * before performing a second save. + * So if the order of the observable values is important, + * then we should use concat map. + * If we want to perform our observables in parallel, + * then we use merge map. + * And with these we have given the concat map and the merge map + * operators. What we are going to do next is we are going + * to cover two other very commonly used mapping operators + * exhaust map and switch map. + */ + + ngOnInit() { + this.form.valueChanges + .pipe( + filter(() => this.form.valid), + mergeMap(changes => this.saveCourse(changes)) + ) + .subscribe(); + } + + saveCourse(changes) { + return fromPromise(fetch(`/api/courses/${this.course.id}`, { + method: 'PUT', + body: JSON.stringify(changes), + headers: { + 'content-type': 'application/json' + } + })); } + ngAfterViewInit() {} + save() { this.store.saveCourse(this.course.id, this.form.value) .subscribe(