|
@@ -25,7 +25,7 @@
|
25
|
25
|
|
26
|
26
|
### Part 0.0 - Familiarize Yourself with the Project Structure
|
27
|
27
|
|
28
|
|
-* Your project contains two files, ``index.html``, ``index.js`` and ``styles.css``, providing you with the basic html structure of the project and some basic styles.
|
|
28
|
+* Your project contains two files, ``index.html`` and ``styles.css``, providing you with the basic html structure of the project and some basic styles.
|
29
|
29
|
|
30
|
30
|
### Part 0.1 - Serve your project
|
31
|
31
|
|
|
@@ -41,7 +41,6 @@
|
41
|
41
|
* For the ``async`` attribute, assign it a value of ``true``. Typically, when an HTML file hits a ``<script>`` tag, it stops parsing the HTML, downloads the JavaScript, and then executes the JavaScript. ``async="true"`` overrides this behavior, instead allowing the HTML to be parsed **alongside** downloading the JavaScript. Once the JavaScript is finished downloading, the HTML parsing is paused and the script executes. [Read more about async and defer](https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html)
|
42
|
42
|
* At the top of your ``index.html`` file, declare a new variable called ``currentUser`` and assign it your YouAreEll username (You should have made one in the previous YouAreEll lab).
|
43
|
43
|
* [Add an event listener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) to the [``window``](https://developer.mozilla.org/en-US/docs/Web/API/Window) object. The ``addEventListener`` method takes two parameters, the type of event you're listening for (examples include "load", "click", "keydown", etc), and a function reference, known as a [callback](), representing the function you want to invoke when the event occurs. Wraping code in a "load" event listener attached to the ``window`` object will insure that your code is only ran once the page has loaded.
|
44
|
|
-*
|
45
|
44
|
```javascript
|
46
|
45
|
let userId = "dominiqueclarke";
|
47
|
46
|
|
|
@@ -102,14 +101,14 @@ window.addEventListener("load", function () {
|
102
|
101
|
|
103
|
102
|
### Part 3.0 - Creating AJAX HTTP Requests
|
104
|
103
|
|
105
|
|
-* In ``message-service.js``, create a method called ``getAllMessages``, which takes a single parameter, ``userId``.
|
|
104
|
+* In ``message-service.js``, create a method called ``getAllMessages``, which takes 0 parameters
|
106
|
105
|
* Create a ``XMLHTTPRequest`` (XHR) object and assign it to a variable called ``request``. XMLHttpRequest (XHR) objects interact with servers through ``HTTP`` requests. You can retrieve data from a URL without having to do a full page refresh. XMLHttpRequest is used heavily in [Ajax](https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX/Getting_Started) programming.
|
107
|
106
|
* Use the [``open``](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open) method on the ``request`` object, passing the type of ``HTTP`` request you'd like to make and the request endpoint as the first two arguments. To get all the global messages, use the ``/messages/`` endpoint. Refer back to the original [YouAreEll lab](https://git.zipcode.rocks/ZipCodeWilmington/YouAreEll) for documentation on the API if necessary.
|
108
|
107
|
* Use the [``send``](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send) method to send the request. This method takes an optional parameter of the request ``body`` when necessary.
|
109
|
108
|
```javascript
|
110
|
109
|
export default class MessageService {
|
111
|
110
|
|
112
|
|
- getAllMessages(userId) {
|
|
111
|
+ getAllMessages() {
|
113
|
112
|
let request = new XMLHttpRequest();
|
114
|
113
|
|
115
|
114
|
request.open("GET", "http://zipcode.rocks:8085/messages");
|
|
@@ -123,7 +122,7 @@ export default class MessageService {
|
123
|
122
|
|
124
|
123
|
* We've configured and sent the request, but what happens when we receive the request back? We can define a function to be used once the response is received using the [``onload``](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload) property of the ``request`` object.
|
125
|
124
|
```javascript
|
126
|
|
-getAllMessages(userId) {
|
|
125
|
+getAllMessages() {
|
127
|
126
|
let request = new XMLHttpRequest();
|
128
|
127
|
|
129
|
128
|
// Setup our listener to process compeleted requests
|
|
@@ -139,7 +138,7 @@ getAllMessages(userId) {
|
139
|
138
|
* If the status is greater than or equal to 200 and less than 300, than we have a successful response. Else, we have an error. Create an if/else statement to handle the response or error.
|
140
|
139
|
* The response is stored in the ``responseText`` property of the ``request`` object as an array of [JSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) objects. To convert it into an array of JavaScript objects, use ``JSON.parse(request.responseText)``.
|
141
|
140
|
```javascript
|
142
|
|
-getAllMessages(userId) {
|
|
141
|
+getAllMessages() {
|
143
|
142
|
let request = new XMLHttpRequest();
|
144
|
143
|
|
145
|
144
|
// Setup our listener to process compeleted requests
|
|
@@ -165,64 +164,21 @@ const messageService = new MessageService(userId);
|
165
|
164
|
|
166
|
165
|
window.addEventListener("load", function () {
|
167
|
166
|
document.getElementById("greeting").innerHTML = `Welcome ${userId}!`;
|
168
|
|
- messageService.getAllMessages(userId);
|
|
167
|
+ messageService.getAllMessages();
|
169
|
168
|
});
|
170
|
169
|
```
|
171
|
170
|
* Refresh your browser. Right click on the page and select ``inspect``. When the dev tools container pops up, click the ``console`` tab. Once the response is returned, you should see the returned array of messages printed to the console.
|
172
|
171
|
|
173
|
|
-<!-- ## Part 3.7 - Convert Message Array to Threads Object
|
174
|
|
-
|
175
|
|
-* Our API returns an array of messages from various users. Create a helper method on ``MessageService`` class called ``parseThreads`` to convert this array into an object. Our object will act kinda like a hashmap, with a key representing the ``fromId``, and the value being an array of messages with that ``fromId``. ``parseThreads`` should take one parameter, the array of ``messages``. Looping through the array, check to see if the ``threads`` object has a key for the current message's ``fromId``. If not, first create the new key and assign it an empty array, then push the message to the array. If the ``threads`` object does contain a key representing the current message's ``fromId``, push the message to the array. Once you've iterated through the messages, return the ``threads`` object.
|
176
|
|
-
|
177
|
|
-```javascript
|
178
|
|
-parseThreads(messages) {
|
179
|
|
- const threads = {};
|
180
|
|
-
|
181
|
|
- messages.forEach(message => {
|
182
|
|
- if (!threads.hasOwnProperty(message.fromid)) {
|
183
|
|
- threads[message.fromid] = [];
|
184
|
|
- threads[message.fromid].push(message);
|
185
|
|
- } else {
|
186
|
|
- threads[message.fromid].push(message);
|
187
|
|
- }
|
188
|
|
- });
|
189
|
|
-
|
190
|
|
- return threads;
|
191
|
|
-}
|
192
|
|
-```
|
193
|
|
-* Using the ``parseThreads`` method, edit your ``getAllMessages`` function to parse the ``response.responseText`` from an array to an object.
|
194
|
|
- * You may be tempted to call the function using the ``this`` keyword. Keep in mind that ``this`` within the ``onload`` function refers to the ``request`` object, not the ``MessageService`` object. In order to refer to the ``MessageService`` within ``request.onload``, we need to capture the context of ``MessageService`` in a new variable called ``self``. This will capture the context of the ``MessageService`` object, and you can use ``self`` as opposed to ``this`` to refer to the ``MessageService`` object.
|
195
|
|
-```javascript
|
196
|
|
-getAllMessages(userId) {
|
197
|
|
- let request = new XMLHttpRequest();
|
198
|
|
- let self = this;
|
199
|
|
-
|
200
|
|
- // Setup our listener to process compeleted requests
|
201
|
|
- request.onload = function() {
|
202
|
|
- if (request.status >= 200 && request.status < 300) {
|
203
|
|
- console.log(self.parseThreads(JSON.parse(request.responseText))); // 'This is the returned text.'
|
204
|
|
- } else {
|
205
|
|
- console.log('Error: ' + request.status); // An error occurred during the request.
|
206
|
|
- }
|
207
|
|
- };
|
208
|
|
-
|
209
|
|
- request.open("GET", `${this.apiUri}/ids/${userId}/messages`);
|
210
|
|
-
|
211
|
|
- request.send();
|
212
|
|
-}
|
213
|
|
-``` -->
|
214
|
|
-* Refresh the page and check your console for your outputted ``threads`` object.
|
215
|
|
-
|
216
|
172
|
### Part 4.0 - Promise based AJAX requests
|
217
|
173
|
|
218
|
|
-* Our current ``getAllMessages`` method has some issues. XMLHTTPRequests are processed asynchronously using callbacks. Callbacks cannot contain a return value. This makes it difficult to pass back a value to ``index.js`` where this ``messageService.getAllMessages(userId)`` is being called. Fortunately, we can alieviate this issue using [``promises``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
|
|
174
|
+* Our current ``getAllMessages`` method has some issues. XMLHTTPRequests are processed asynchronously using callbacks. Callbacks cannot contain a return value. This makes it difficult to pass back a value to ``index.js`` where this ``messageService.getAllMessages()`` is being called. Fortunately, we can alieviate this issue using [``promises``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
|
219
|
175
|
* A [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) is an object representing a contract to preform some task asynchronous (often, an ``HTTP`` request), providing a value (often, an ``HTTP`` response) when the task is complete.
|
220
|
176
|
* Promises allow us to continue running syncronous code while waiting for for the execution of the promised task.
|
221
|
177
|
* Promises allow us to specify a function that should be run once the task is complete using the ``then`` method.
|
222
|
178
|
* Promises are tricky. Familiarize yourself with Promises with [this tutorial](https://www.sitepoint.com/overview-javascript-promises/)
|
223
|
179
|
* Wrap your ``request.onload`` function in a ``new`` ``Promise``;
|
224
|
180
|
```javascript
|
225
|
|
-getAllMessages(userId) {
|
|
181
|
+getAllMessages() {
|
226
|
182
|
const request = new XMLHttpRequest();
|
227
|
183
|
|
228
|
184
|
new Promise(function (resolve, reject) {
|
|
@@ -244,7 +200,7 @@ getAllMessages(userId) {
|
244
|
200
|
```
|
245
|
201
|
* If the request is successful, ``resolve`` the ``promise`` passing in the ``threads`` object``
|
246
|
202
|
```javascript
|
247
|
|
-getAllMessages(userId) {
|
|
203
|
+getAllMessages() {
|
248
|
204
|
const request = new XMLHttpRequest();
|
249
|
205
|
|
250
|
206
|
new Promise(function (resolve, reject) {
|
|
@@ -267,7 +223,7 @@ getAllMessages(userId) {
|
267
|
223
|
```
|
268
|
224
|
* If the request returns an error, ``reject`` the ``promise`` passing in the ``threads`` object``
|
269
|
225
|
```javascript
|
270
|
|
-getAllMessages(userId) {
|
|
226
|
+getAllMessages() {
|
271
|
227
|
const request = new XMLHttpRequest();
|
272
|
228
|
|
273
|
229
|
new Promise(function (resolve, reject) {
|
|
@@ -295,7 +251,7 @@ getAllMessages(userId) {
|
295
|
251
|
* The [``then``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) method is part of the ``Promise`` interface. It takes up to two parameters: a ``callback`` function for the success case and a callback function for the failure case of the ``Promise``.
|
296
|
252
|
* If the ``Promise`` is successful, the first parameter (the success callback), is executed. If the ``Promise`` results in an error, the second parameter (the failure callback), is excuted.
|
297
|
253
|
```javascript
|
298
|
|
-getAllMessages(userId) {
|
|
254
|
+getAllMessages() {
|
299
|
255
|
const request = new XMLHttpRequest();
|
300
|
256
|
|
301
|
257
|
new Promise(function (resolve, reject) {
|
|
@@ -330,7 +286,7 @@ getAllMessages(userId) {
|
330
|
286
|
```
|
331
|
287
|
* When the callbacks are executed, the receive a special parameter. The success callback receives the value passed to the ``resolve`` method, while the failure callback receives the value passed to the ``reject`` method.
|
332
|
288
|
```javascript
|
333
|
|
-getAllMessages(userId) {
|
|
289
|
+getAllMessages() {
|
334
|
290
|
const request = new XMLHttpRequest();
|
335
|
291
|
|
336
|
292
|
new Promise(function (resolve, reject) {
|
|
@@ -374,7 +330,7 @@ getAllMessages(userId) {
|
374
|
330
|
* Remove the ``then`` method, ``successCallback`` declaration and ``errorCallback`` declaration from ``getAllMessages``.
|
375
|
331
|
* ``return`` the Promise from the ``getAllMessages`` method. This will allow us to call the ``then`` method, passing in the appropriate success and failure callbacks, elsewhere.
|
376
|
332
|
```javascript
|
377
|
|
-getAllMessages(userId) {
|
|
333
|
+getAllMessages() {
|
378
|
334
|
const request = new XMLHttpRequest();
|
379
|
335
|
|
380
|
336
|
return new Promise(function (resolve, reject) {
|
|
@@ -403,7 +359,7 @@ getAllMessages(userId) {
|
403
|
359
|
```
|
404
|
360
|
* Navigate back to your ``index.js`` file. ``getAllMessages`` now returns a ``Promise``. We can now use the ``then`` method to specify a ``callback`` function to be executed in case of success or failure of that ``Promise``. Call ``.then`` on ``messageService.getAllMessages``, reimplementing the original code.
|
405
|
361
|
```javascript
|
406
|
|
-messageService.getAllMessages(userId)
|
|
362
|
+messageService.getAllMessages()
|
407
|
363
|
.then(successCallback, errorCallback);
|
408
|
364
|
|
409
|
365
|
function successCallback(response) {
|
|
@@ -430,7 +386,7 @@ const messageService = new MessageService(userId);
|
430
|
386
|
window.addEventListener("load", function () {
|
431
|
387
|
|
432
|
388
|
document.getElementById("greeting").innerHTML = `Welcome ${userId}!`;
|
433
|
|
- messageService.getAllMessages(userId)
|
|
389
|
+ messageService.getAllMessages()
|
434
|
390
|
.then(successCallback, errorCallback);
|
435
|
391
|
|
436
|
392
|
function successCallback(response) {
|
|
@@ -523,7 +479,7 @@ function populateThread(messages) {
|
523
|
479
|
```javascript
|
524
|
480
|
window.addEventListener("load", function () {
|
525
|
481
|
document.getElementById("greeting").innerHTML = `Welcome ${userId}!`;
|
526
|
|
- messageService.getAllMessages(userId)
|
|
482
|
+ messageService.getAllMessages()
|
527
|
483
|
.then(successCallback, errorCallback);
|
528
|
484
|
|
529
|
485
|
function successCallback(response) {
|