1 00:00:00,219 --> 00:00:03,722 You've learned how to create and consume a promise, as well as 2 00:00:03,722 --> 00:00:07,965 how to chain together a sequence of promises and handle rejected promises. 3 00:00:07,965 --> 00:00:11,762 Now we're going to jump back into our People in Space project and 4 00:00:11,762 --> 00:00:14,658 convert parts of it from callbacks to promises. 5 00:00:14,658 --> 00:00:17,616 Open the file promises.js. 6 00:00:17,616 --> 00:00:18,374 In this file, 7 00:00:18,374 --> 00:00:22,886 you should see code that's very similar to the code you wrote in the previous stage. 8 00:00:22,886 --> 00:00:29,423 Remember, a promise is the eventual value or result of an asynchronous operation. 9 00:00:29,423 --> 00:00:33,614 So which part of the program is set to execute at some point later, 10 00:00:33,614 --> 00:00:35,532 once it has the data it needs? 11 00:00:35,532 --> 00:00:39,877 Well, in the function getJSON, the callback function assigned 12 00:00:39,877 --> 00:00:43,594 to onload is invoked once data is returned from the API. 13 00:00:43,594 --> 00:00:45,813 So we can convert this into a promise. 14 00:00:45,813 --> 00:00:52,414 First, I'll set getJSON to return a promise using the Promise constructor. 15 00:00:52,414 --> 00:00:58,802 I'll pass the constructor a callback with the parameters resolve and reject. 16 00:01:00,848 --> 00:01:06,379 Then place the body of getJSON within the Promise constructor callback. 17 00:01:08,991 --> 00:01:14,984 Next, when the API data loads, if the status of the response is 200, 18 00:01:14,984 --> 00:01:17,650 we'll parse that data to JSON. 19 00:01:17,650 --> 00:01:21,812 And instead of invoking a callback function here, 20 00:01:21,812 --> 00:01:26,456 I'm going to call resolve and pass it the variable data, 21 00:01:26,456 --> 00:01:32,281 which will change the status of the promise from pending to fulfilled. 22 00:01:32,281 --> 00:01:37,733 Else if the status code is something other than 200, 23 00:01:37,733 --> 00:01:42,150 I'll reject the promise by calling reject. 24 00:01:42,150 --> 00:01:48,666 And I'll again use the Error constructor here to display the stack trace, 25 00:01:48,666 --> 00:01:55,924 as well as the response status text as the rejection reason with xhr.statusText. 26 00:01:55,924 --> 00:01:58,986 This should hopefully provide a more meaningful error. 27 00:01:58,986 --> 00:02:03,713 Now you can delete the callback parameter from the getJSON function signature, 28 00:02:03,713 --> 00:02:07,341 since it no longer requires a callback function passed to it. 29 00:02:07,341 --> 00:02:12,007 Now if at some point there's a network connectivity issue, 30 00:02:12,007 --> 00:02:14,943 a status code wouldn't be provided. 31 00:02:14,943 --> 00:02:20,286 So let's also use the onerror event handler on the xhr object 32 00:02:20,286 --> 00:02:27,011 to reject the promise if the HttpRequest fails due to connectivity issues. 33 00:02:27,011 --> 00:02:32,546 I'll again pass reject, the error constructor 34 00:02:32,546 --> 00:02:37,542 with the message A network error occurred. 35 00:02:37,542 --> 00:02:41,359 All right, getJSON is now all set up to return a promise object. 36 00:02:41,359 --> 00:02:46,162 Next, down in the EventListener, we still call getJSON, 37 00:02:46,162 --> 00:02:51,171 but we no longer need to provide it getProfiles as a callback. 38 00:02:51,171 --> 00:02:55,887 Instead, we can call then on the getJSON promise and 39 00:02:55,887 --> 00:02:59,218 pass it a reference to getProfiles. 40 00:02:59,218 --> 00:03:01,851 Promises get executed in sequence. 41 00:03:01,851 --> 00:03:07,039 Each then method that's chained on to the main promise returns a promise of its own. 42 00:03:07,039 --> 00:03:12,118 They each get executed sequentially, once the previous promise is fulfilled. 43 00:03:12,118 --> 00:03:15,656 In other words, something happens after something else is resolved. 44 00:03:15,656 --> 00:03:20,025 So far, this is going to fetch the data from the open notify API. 45 00:03:20,025 --> 00:03:25,583 Then if that task is resolved, it's going to pass the return data down to the then 46 00:03:25,583 --> 00:03:31,333 method, which is then used in getProfiles to request data from the Wikipedia API. 47 00:03:31,333 --> 00:03:36,215 Next, I'll chain another then method to do something with those results. 48 00:03:36,215 --> 00:03:41,856 For now, I'll log the data to the console by passing then a function with 49 00:03:41,856 --> 00:03:47,700 the parameter data, which represents the data returned by getProfiles. 50 00:03:47,700 --> 00:03:52,067 So once the promise is fulfilled, this handler function will be called 51 00:03:52,067 --> 00:03:57,108 asynchronously, and it's going to return a value, the Wikipedia data in JSON. 52 00:03:57,108 --> 00:04:02,383 Let's not forget to add the catch method at the end to handle rejected promises. 53 00:04:02,383 --> 00:04:07,622 I'll pass catch a function that takes the rejection reason as a parameter and 54 00:04:07,622 --> 00:04:09,244 logs it to the console. 55 00:04:10,518 --> 00:04:14,827 Finally, we need to make a few changes in the getProfiles function. 56 00:04:14,827 --> 00:04:19,465 First, omit the callback passed to getJSON. 57 00:04:19,465 --> 00:04:21,740 Then specify the return keyword, 58 00:04:21,740 --> 00:04:26,689 since we're now returning a promise object during each iteration of map. 59 00:04:26,689 --> 00:04:34,494 Let's also capture the results of the map operation in a variable named profiles, 60 00:04:34,494 --> 00:04:38,409 then have the function return profiles. 61 00:04:39,440 --> 00:04:42,046 Before testing your code in the browser, 62 00:04:42,046 --> 00:04:46,297 make sure to update index.html to use the latest JavaScript file. 63 00:04:46,297 --> 00:04:54,520 Change the source value of the script tag from callbacks.js to promises.js. 64 00:04:55,962 --> 00:04:58,880 Over in the browser, refresh. 65 00:04:58,880 --> 00:05:03,848 Then click the view button, and instead of seeing the Wikipedia data logged to 66 00:05:03,848 --> 00:05:09,051 the console, we're getting an array containing six resolved promise objects. 67 00:05:09,051 --> 00:05:14,007 And that's correct because it's now getJSON's job to return a resolved or 68 00:05:14,007 --> 00:05:15,329 rejected promise. 69 00:05:15,329 --> 00:05:20,404 In fact, if there's an issue with the Wikipedia request, for 70 00:05:20,404 --> 00:05:27,110 example, I'll mistype the URL, we'll instead see six rejected promise objects 71 00:05:27,110 --> 00:05:32,795 in the console with the rejection reason, A network error occurred. 72 00:05:36,287 --> 00:05:39,613 So instead of six separate promise objects, 73 00:05:39,613 --> 00:05:44,513 we need getProfiles to return a single resolved promise when all of 74 00:05:44,513 --> 00:05:48,288 the promises from the Map function have resolved. 75 00:05:48,288 --> 00:05:52,050 For example, an array containing the astronaut profile objects, 76 00:05:52,050 --> 00:05:54,697 we can then pass to the generateHTML function. 77 00:05:54,697 --> 00:05:59,401 I'll teach you how to do just that in the next video with promise.all.