Skip to content

Commit 97a8bde

Browse files
committed
Some small touches to Chapter 21
1 parent 9798d3b commit 97a8bde

File tree

2 files changed

+18
-26
lines changed

2 files changed

+18
-26
lines changed

21_skillsharing.md

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,15 @@ This uses a similar convention as the file server from the [previous chapter](no
274274

275275
The ((talk))s that have been proposed are stored in the `talks` property of the server, an object whose property names are the talk titles. These will be exposed as HTTP ((resource))s under `/talks/[title]`, so we need to add handlers to our router that implement the various methods that clients can use to work with them.
276276

277-
{{index "GET method", "404 (HTTP status code)"}}
277+
{{index "GET method", "404 (HTTP status code)" "hasOwn function"}}
278278

279279
The handler for requests that `GET` a single talk must look up the talk and respond either with the talk's JSON data or with a 404 error response.
280280

281281
```{includeCode: ">code/skillsharing/skillsharing_server.mjs"}
282282
const talkPath = /^\/talks\/([^\/]+)$/;
283283
284284
router.add("GET", talkPath, async (server, title) => {
285-
if (title in server.talks) {
285+
if (Object.hasOwn(server.talks, title)) {
286286
return {body: JSON.stringify(server.talks[title]),
287287
headers: {"Content-Type": "application/json"}};
288288
} else {
@@ -297,7 +297,7 @@ Deleting a talk is done by removing it from the `talks` object.
297297

298298
```{includeCode: ">code/skillsharing/skillsharing_server.mjs"}
299299
router.add("DELETE", talkPath, async (server, title) => {
300-
if (title in server.talks) {
300+
if (Object.hasOwn(server.talks, title)) {
301301
delete server.talks[title];
302302
server.updated();
303303
}
@@ -372,7 +372,7 @@ router.add("POST", /^\/talks\/([^\/]+)\/comments$/,
372372
typeof comment.author != "string" ||
373373
typeof comment.message != "string") {
374374
return {status: 400, body: "Bad comment data"};
375-
} else if (title in server.talks) {
375+
} else if (Object.hasOwn(server.talks, title)) {
376376
server.talks[title].comments.push(comment);
377377
server.updated();
378378
return {status: 204};
@@ -396,10 +396,8 @@ There will be multiple places in which we have to send an array of talks to the
396396

397397
```{includeCode: ">code/skillsharing/skillsharing_server.mjs"}
398398
SkillShareServer.prototype.talkResponse = function() {
399-
let talks = [];
400-
for (let title of Object.keys(this.talks)) {
401-
talks.push(this.talks[title]);
402-
}
399+
let talks = Object.keys(this.talks)
400+
.map(title => this.talks[title]);
403401
return {
404402
body: JSON.stringify(talks),
405403
headers: {"Content-Type": "application/json",
@@ -468,7 +466,7 @@ SkillShareServer.prototype.updated = function() {
468466
That concludes the server code. If we create an instance of `SkillShareServer` and start it on port 8000, the resulting HTTP server serves files from the `public` subdirectory alongside a talk-managing interface under the `/talks` URL.
469467

470468
```{includeCode: ">code/skillsharing/skillsharing_server.mjs"}
471-
new SkillShareServer(Object.create(null)).start(8000);
469+
new SkillShareServer({}).start(8000);
472470
```
473471

474472
## The client
@@ -809,14 +807,10 @@ Extend the server so that it stores the talk data to disk and automatically relo
809807

810808
The simplest solution I can come up with is to encode the whole `talks` object as ((JSON)) and dump it to a file with `writeFile`. There is already a method (`updated`) that is called every time the server's data changes. It can be extended to write the new data to disk.
811809

812-
{{index "readFile function"}}
810+
{{index "readFile function", "JSON.parse function"}}
813811

814812
Pick a ((file))name, for example `./talks.json`. When the server starts, it can try to read that file with `readFile`, and if that succeeds, the server can use the file's contents as its starting data.
815813

816-
{{index prototype, "JSON.parse function"}}
817-
818-
Beware, though. The `talks` object started as a prototype-less object so that the `in` operator could reliably be used. `JSON.parse` will return regular objects with `Object.prototype` as their prototype. If you use JSON as your file format, you'll have to copy the properties of the object returned by `JSON.parse` into a new, prototype-less object.
819-
820814
hint}}
821815

822816
### Comment field resets
@@ -831,7 +825,7 @@ In a heated discussion, where multiple people are adding comments at the same ti
831825

832826
{{index "comment field reset (exercise)", template, "syncState method"}}
833827

834-
The best way to do this is probably to make talks component objects, with a `syncState` method, so that they can be updated to show a modified version of the talk. During normal operation, the only way a talk can be changed is by adding more comments, so the `syncState` method can be relatively simple.
828+
The best way to do this is probably to make the talk component an object, with a `syncState` method, so that they can be updated to show a modified version of the talk. During normal operation, the only way a talk can be changed is by adding more comments, so the `syncState` method can be relatively simple.
835829

836830
The difficult part is that, when a changed list of talks comes in, we have to reconcile the existing list of DOM components with the talks on the new list—deleting components whose talk was deleted and updating components whose talk changed.
837831

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,10 @@
11
// This isn't a stand-alone file, only a redefinition of a few
22
// fragments from skillsharing/skillsharing_server.js
33

4-
const {readFileSync, writeFile} = require("fs");
4+
import {readFileSync, writeFile} from "node:fs";
55

66
const fileName = "./talks.json";
77

8-
function loadTalks() {
9-
let json;
10-
try {
11-
json = JSON.parse(readFileSync(fileName, "utf8"));
12-
} catch (e) {
13-
json = {};
14-
}
15-
return Object.assign(Object.create(null), json);
16-
}
17-
188
SkillShareServer.prototype.updated = function() {
199
this.version++;
2010
let response = this.talkResponse();
@@ -26,5 +16,13 @@ SkillShareServer.prototype.updated = function() {
2616
});
2717
};
2818

19+
function loadTalks() {
20+
try {
21+
return JSON.parse(readFileSync(fileName, "utf8"));
22+
} catch (e) {
23+
return {};
24+
}
25+
}
26+
2927
// The line that starts the server must be changed to
3028
new SkillShareServer(loadTalks()).start(8000);

0 commit comments

Comments
 (0)