|
|
|
|
25
|
|
25
|
|
26
|
### Part 0.0 - Familiarize Yourself with the Project Structure
|
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
|
### Part 0.1 - Serve your project
|
30
|
### Part 0.1 - Serve your project
|
31
|
|
31
|
|
|
|
|
|
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)
|
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
|
* 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).
|
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
|
* [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.
|
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
|
```javascript
|
44
|
```javascript
|
46
|
let userId = "dominiqueclarke";
|
45
|
let userId = "dominiqueclarke";
|
47
|
|
46
|
|
|
|
|
|
102
|
|
101
|
|
103
|
### Part 3.0 - Creating AJAX HTTP Requests
|
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
|
* 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.
|
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
|
* 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.
|
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
|
* 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.
|
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
|
```javascript
|
108
|
```javascript
|
110
|
export default class MessageService {
|
109
|
export default class MessageService {
|
111
|
|
110
|
|
112
|
- getAllMessages(userId) {
|
|
|
|
|
111
|
+ getAllMessages() {
|
113
|
let request = new XMLHttpRequest();
|
112
|
let request = new XMLHttpRequest();
|
114
|
|
113
|
|
115
|
request.open("GET", "http://zipcode.rocks:8085/messages");
|
114
|
request.open("GET", "http://zipcode.rocks:8085/messages");
|
|
|
|
|
123
|
|
122
|
|
124
|
* 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.
|
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
|
```javascript
|
124
|
```javascript
|
126
|
-getAllMessages(userId) {
|
|
|
|
|
125
|
+getAllMessages() {
|
127
|
let request = new XMLHttpRequest();
|
126
|
let request = new XMLHttpRequest();
|
128
|
|
127
|
|
129
|
// Setup our listener to process compeleted requests
|
128
|
// Setup our listener to process compeleted requests
|
|
|
|
|
139
|
* 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.
|
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
|
* 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)``.
|
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
|
```javascript
|
140
|
```javascript
|
142
|
-getAllMessages(userId) {
|
|
|
|
|
141
|
+getAllMessages() {
|
143
|
let request = new XMLHttpRequest();
|
142
|
let request = new XMLHttpRequest();
|
144
|
|
143
|
|
145
|
// Setup our listener to process compeleted requests
|
144
|
// Setup our listener to process compeleted requests
|
|
|
|
|
165
|
|
164
|
|
166
|
window.addEventListener("load", function () {
|
165
|
window.addEventListener("load", function () {
|
167
|
document.getElementById("greeting").innerHTML = `Welcome ${userId}!`;
|
166
|
document.getElementById("greeting").innerHTML = `Welcome ${userId}!`;
|
168
|
- messageService.getAllMessages(userId);
|
|
|
|
|
167
|
+ messageService.getAllMessages();
|
169
|
});
|
168
|
});
|
170
|
```
|
169
|
```
|
171
|
* 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.
|
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
|
### Part 4.0 - Promise based AJAX requests
|
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
|
* 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.
|
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
|
* Promises allow us to continue running syncronous code while waiting for for the execution of the promised task.
|
176
|
* Promises allow us to continue running syncronous code while waiting for for the execution of the promised task.
|
221
|
* Promises allow us to specify a function that should be run once the task is complete using the ``then`` method.
|
177
|
* Promises allow us to specify a function that should be run once the task is complete using the ``then`` method.
|
222
|
* Promises are tricky. Familiarize yourself with Promises with [this tutorial](https://www.sitepoint.com/overview-javascript-promises/)
|
178
|
* Promises are tricky. Familiarize yourself with Promises with [this tutorial](https://www.sitepoint.com/overview-javascript-promises/)
|
223
|
* Wrap your ``request.onload`` function in a ``new`` ``Promise``;
|
179
|
* Wrap your ``request.onload`` function in a ``new`` ``Promise``;
|
224
|
```javascript
|
180
|
```javascript
|
225
|
-getAllMessages(userId) {
|
|
|
|
|
181
|
+getAllMessages() {
|
226
|
const request = new XMLHttpRequest();
|
182
|
const request = new XMLHttpRequest();
|
227
|
|
183
|
|
228
|
new Promise(function (resolve, reject) {
|
184
|
new Promise(function (resolve, reject) {
|
|
|
|
|
244
|
```
|
200
|
```
|
245
|
* If the request is successful, ``resolve`` the ``promise`` passing in the ``threads`` object``
|
201
|
* If the request is successful, ``resolve`` the ``promise`` passing in the ``threads`` object``
|
246
|
```javascript
|
202
|
```javascript
|
247
|
-getAllMessages(userId) {
|
|
|
|
|
203
|
+getAllMessages() {
|
248
|
const request = new XMLHttpRequest();
|
204
|
const request = new XMLHttpRequest();
|
249
|
|
205
|
|
250
|
new Promise(function (resolve, reject) {
|
206
|
new Promise(function (resolve, reject) {
|
|
|
|
|
267
|
```
|
223
|
```
|
268
|
* If the request returns an error, ``reject`` the ``promise`` passing in the ``threads`` object``
|
224
|
* If the request returns an error, ``reject`` the ``promise`` passing in the ``threads`` object``
|
269
|
```javascript
|
225
|
```javascript
|
270
|
-getAllMessages(userId) {
|
|
|
|
|
226
|
+getAllMessages() {
|
271
|
const request = new XMLHttpRequest();
|
227
|
const request = new XMLHttpRequest();
|
272
|
|
228
|
|
273
|
new Promise(function (resolve, reject) {
|
229
|
new Promise(function (resolve, reject) {
|
|
|
|
|
295
|
* 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``.
|
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
|
* 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.
|
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
|
```javascript
|
253
|
```javascript
|
298
|
-getAllMessages(userId) {
|
|
|
|
|
254
|
+getAllMessages() {
|
299
|
const request = new XMLHttpRequest();
|
255
|
const request = new XMLHttpRequest();
|
300
|
|
256
|
|
301
|
new Promise(function (resolve, reject) {
|
257
|
new Promise(function (resolve, reject) {
|
|
|
|
|
330
|
```
|
286
|
```
|
331
|
* 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.
|
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
|
```javascript
|
288
|
```javascript
|
333
|
-getAllMessages(userId) {
|
|
|
|
|
289
|
+getAllMessages() {
|
334
|
const request = new XMLHttpRequest();
|
290
|
const request = new XMLHttpRequest();
|
335
|
|
291
|
|
336
|
new Promise(function (resolve, reject) {
|
292
|
new Promise(function (resolve, reject) {
|
|
|
|
|
374
|
* Remove the ``then`` method, ``successCallback`` declaration and ``errorCallback`` declaration from ``getAllMessages``.
|
330
|
* Remove the ``then`` method, ``successCallback`` declaration and ``errorCallback`` declaration from ``getAllMessages``.
|
375
|
* ``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.
|
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
|
```javascript
|
332
|
```javascript
|
377
|
-getAllMessages(userId) {
|
|
|
|
|
333
|
+getAllMessages() {
|
378
|
const request = new XMLHttpRequest();
|
334
|
const request = new XMLHttpRequest();
|
379
|
|
335
|
|
380
|
return new Promise(function (resolve, reject) {
|
336
|
return new Promise(function (resolve, reject) {
|
|
|
|
|
403
|
```
|
359
|
```
|
404
|
* 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.
|
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
|
```javascript
|
361
|
```javascript
|
406
|
-messageService.getAllMessages(userId)
|
|
|
|
|
362
|
+messageService.getAllMessages()
|
407
|
.then(successCallback, errorCallback);
|
363
|
.then(successCallback, errorCallback);
|
408
|
|
364
|
|
409
|
function successCallback(response) {
|
365
|
function successCallback(response) {
|
|
|
|
|
430
|
window.addEventListener("load", function () {
|
386
|
window.addEventListener("load", function () {
|
431
|
|
387
|
|
432
|
document.getElementById("greeting").innerHTML = `Welcome ${userId}!`;
|
388
|
document.getElementById("greeting").innerHTML = `Welcome ${userId}!`;
|
433
|
- messageService.getAllMessages(userId)
|
|
|
|
|
389
|
+ messageService.getAllMessages()
|
434
|
.then(successCallback, errorCallback);
|
390
|
.then(successCallback, errorCallback);
|
435
|
|
391
|
|
436
|
function successCallback(response) {
|
392
|
function successCallback(response) {
|
|
|
|
|
523
|
```javascript
|
479
|
```javascript
|
524
|
window.addEventListener("load", function () {
|
480
|
window.addEventListener("load", function () {
|
525
|
document.getElementById("greeting").innerHTML = `Welcome ${userId}!`;
|
481
|
document.getElementById("greeting").innerHTML = `Welcome ${userId}!`;
|
526
|
- messageService.getAllMessages(userId)
|
|
|
|
|
482
|
+ messageService.getAllMessages()
|
527
|
.then(successCallback, errorCallback);
|
483
|
.then(successCallback, errorCallback);
|
528
|
|
484
|
|
529
|
function successCallback(response) {
|
485
|
function successCallback(response) {
|