-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExpressBackendExerciseSolution.js
164 lines (147 loc) · 4.6 KB
/
ExpressBackendExerciseSolution.js
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
const express = require('express');
const bodyParser = require('body-parser');
const fetch = require('isomorphic-unfetch');
const port = 8000;
const server = express();
server.use(bodyParser.json({strict: false}));
server.use(bodyParser.urlencoded({extended: false}));
const SWAPI_URL = 'https://swapi.co/api';
/* Route Input:
* - Query Parameter: Integer
*
* Route Output:
* - Star Wars Character Profile corresponding to
* that integer
*/
server.get('/character/:id', (req, res, next) => {
fetch(`${SWAPI_URL}/people/${req.params.id}`)
.then(response => response.json())
.then(data => {
res.send(data);
});
});
/*
* This way of writing this route uses the old, Promise-based JS syntax.
* Notice how much extra code/funk we need compared to the solution below,
* which uses async/await syntax.
*
* Route Documentation for Reference Solution to Route 1
*
* Route Input:
* - Query Parameter: Integer representing a SW Character
*
* Route Output:
* - List of strings, where each string represents the name of a vehicle used
* by the character given by the query parameter
*/
server.get('/old/character/:id/vehicles', (req, res, next) => {
fetch(`${SWAPI_URL}/people/${req.params.id}`)
.then(response => response.json())
.then(data => data.vehicles)
.then(vehicles => {
return Promise.all(
vehicles.map(url => fetch(url))
);
})
.then(responses => {
return Promise.all(
responses.map(res => res.json())
);
})
.then(vehicles => {
res.send(vehicles.map(vehicle => vehicle.name));
});
});
/*
* This way of writing the route uses new async/await syntax. Notice
* how both fetch() and .json() function calls are async. This means
* that fetching data over the network AND extracting a JSON from the
* server response are BOTH asynchronous operations.
*
* Route Documentation for Reference Solution to Route 1
*
* Route Input:
* - Query Parameter: Integer representing a SW Character
*
* Route Output:
* - List of strings, where each string represents the name of a vehicle used
* by the character given by the query parameter
*/
server.get('/new/character/:id/vehicles', async (req, res, next) => {
const personResponse = await fetch(`${SWAPI_URL}/people/${req.params.id}`);
const personJson = await personResponse.json();
const vehicles = personJson.vehicles;
const vehicleNames = [];
for (let i = 0; i < vehicles.length; i++) {
const vehicleResponse = await fetch(vehicles[i]);
const vehicleJson = await vehicleResponse.json();
vehicleNames.push(vehicleJson.name);
}
res.send(vehicleNames);
});
/*
* Route Documentation for Reference Solution to Bonus Route 2
*
* Route Input:
* - Nothing
*
* Route Output:
* - List of strings, where each string represents the name of a SW character
*
*/
server.get('/allcharacters', async (req, res, next) => {
let url = `${SWAPI_URL}/people`;
const people = [];
while (url !== undefined && url !== null) {
const response = await fetch(url);
const data = await response.json();
const characters = data.results;
for (let i = 0; i < characters.length; i++) {
people.push(characters[i].name);
}
url = data.next;
}
res.send(people);
});
/*
* Since the route is supposed to extract a request body, we should make it
* a PUT route. Although it might make more sense to make it a GET, since we're
* "getting" a resource from the server, requests with bodies are traditionally
* crafted as POST routes.
*
* Route Documentation for Reference Solution to Bonus Route 3
*
* Route Input:
* - List of integer ids corresponding to SW characters
*
* Route Output:
* - List of strings corresponding to the unique vehicles used by requested
* SW characters
*
*/
server.post('/uniquevehicles', async (req, res, next) => {
const resultObj = {};
/* Make list of all vehicle URLs to query for */
const vehicleUrlMap = {};
for (const id of req.body.ids) {
const personResponse = await fetch(`${SWAPI_URL}/people/${id}`);
const personJson = await personResponse.json();
for (const vehicle of personJson.vehicles) {
if (vehicleUrlMap[vehicle] !== true) {
vehicleUrlMap[vehicle] = true;
}
}
}
/* Iterate through map and obtain name using fetch */
const vehicleNames = [];
for (const vehicleUrl in vehicleUrlMap) {
const vehicleResponse = await fetch(vehicleUrl);
const vehicleJson = await vehicleResponse.json();
vehicleNames.push(vehicleJson.name);
}
res.send(vehicleNames);
});
/* Start server */
server.listen(port, () => {
console.log(`Server is listening on port ${port}`);
});