- Useful for asynchronous programming in javascript
Promise
- The object that will eventually be returned by the function.
- All asynchronous functions return a promise.
- 2 traits
- Receives a single argument which is a function
- The function has 2 arguments, a
resolvefunction and arejectfunction- The code written inside the promise needs to use one of these two functions
- Can be waited on using
thenmethod (and other similar methods), or theawaitstatement
States
- Pending (waiting to get the data back from the API)
- Fulfilled (successfully resolved)
- Rejected (error)
fetch()
- A function where you give a URL of an API, then it “fetches” the stuff from the URL
- Returns a promise
- native to JS in the browser
- Convert it to an object that we can use →
response.json()
then(), catch()
Functions that you can call to the returned promise object, takes an argument
then()- Receives a function to be executed when promise is fulfilled
- allows you to do other things asynchronously while promise is not yet fulfilled!
- each
.then()returns a promise
catch()- Receives a function to be executed when promise is rejected
resolve(), reject()
- functions you need to use when creating your own promise
- automatically provided to you by JavaScript when you create a new
Promise resolve()- This function is called when the asynchronous operation inside the Promise succeeds, and it fulfills the Promise.
- The result passed to
resolveis what the Promise will resolve to (i.e., the value you get when the Promise is successful).
reject()- This function is called when the asynchronous operation inside the Promise fails, and it rejects the Promise.
- The argument passed to
rejectis usually an error or a message explaining why the operation failed.
- The names don’t really matter (
resolveorreject) but the ORDERING matters- You can have
new Promise((apple, banana))
- You can have
Introductory Example
function getServerStatus()
{
const result = fetch("/server/status");
// this will NOT work!
console.log("Status from the server: ", result.ok);
}fetchfunction returns aPromise- The fetch function is asynchronous, and it returns a promise.
console.logwill not work.
- The fetch function is asynchronous, and it returns a promise.
- This is the right approach - using
then:
function getServerStatus()
{
const response = fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => res.json())
.then((data) => console.log("Status from the server: ", data))
.catch((error) => console.log("Error fetching data: ", error));
}thenfunction is one of the methods of aPromise.then((res) => res.json())- Reads the response body as a JSON object.
- Returns a Promise that resolves with the parsed JSON data
Example 1
Making your own promise
// adding 2 numbers
function sumAsync(x,y)
{
console.log("1. sumAsync is executed!");
const p = new Promise((resolve,reject) => {
setTimeout(() => {
console.log("4. Resolving sumAsync's Promise after 500ms");
resolve(x+y);
},
500
);
// no need to return anything
console.log("2. sunAsync Promise is initialized");
});
console.log("3. sunAsync has returned the Promise");
return p;
}
// actually using the function
sumAsync(5,7).then((result) => {
console.log("5. The result of the addition is:", result);
});- When something is done successfully, call
resolvewith the result - When you use resolve(x + y), you’re calling the resolve function that JavaScript gives you to indicate that the Promise should resolve successfully with the result of x + y.
- If there were an error and you wanted to reject the Promise, you’d explicitly code the reject in there
A shorthand:
// 1
new Promise((resolve, reject) => {
setTimeout(resolve, 1000);
// Just calls resolve() after 1 second
// shorthand way to call resolve() w/ no arguments after time passes!
});
//2
// Same as:
new Promise((resolve, reject) => {
setTimeout(() => resolve(), 1000);
});
//3
// Same as:
new Promise((resolve, reject) => {
setTimeout(() => resolve(undefined), 1000);
});resolve- You’re passing a reference to the function so it can be called later
() => resolve()- This is creating an anonymous arrow function that will be invoked immediately by
setTimeoutafter 1 second, and inside that anonymous function, you’re callingresolve(). setTimeout(resolve(), 1000);is wrong because you would be callingresolve()immediately and not passing it as a reference tosetTimeout.setTimeoutexpects a function as the first argument and not the result of the function!
- This is creating an anonymous arrow function that will be invoked immediately by
() => resolve(undefined)undefinedis directly being passed. it is passed by default, we’re just explicitly stating that
Example 2
- Adding more error catching
// adding 2 numbers
function sumAsync(x,y)
{
const p = new Promise((resolve,reject) => {
setTimeout(() => {
if (x < 0 || y < 0)
{
reject("Only positives allowed!");
}
else
{
resolve(x+y);
}
}, 500);
});
return p;
}
// actually using the function
sumAsync(5,7).then((result) => {
console.log("The result of the addition is:", result);
}).catch((error) => {
console.log("Error: ", error);
})Example 3
Chaining!
// =========== ORIGINAL ===========
function setup()
{
let promise = fetch("some/url");
promise.then(gotData);
promise.catch(gotErr);
function gotData(response)
{
console.log("Success: ", data);
}
function gotErr(error)
{
console.log("Error: ", error);
}
}
// =========== SHORTENED ===========
// you can chain stuff together
function setup()
{
fetch("some/url")
.then(response => console.log("Success: ", response))
.catch(error => console.log("Error: ", error));
}
// WE NEED TO CONVERT IT TO JSON using .json, which also returns a promise
function setup()
{
fetch("some/url")
.then(response => data.json())
.then(jsonResponse => console.log("Returned json: ", json))
.catch(error => console.log("Error: ", error));
}We need to return when chaining!
fetch(wordnikAPIURL)
.then(response => {
return response.json();
})
.then(json => {
createP(json.word);
return fetch(giphyAPI + json.word);
})
.then(response => {
return response.json();
})
.then(json => {
createImg(json.data[0].images['fixed_height_small'].url);
})
.catch(err => console.log(err));- Need to return in order for the next chain to use it
- Each
.then()automatically wraps its return value in a new Promise!!!
Promise.all()
- requires an array
let promises = [___, ___, ___];
Promise.all(promises)
.then((result) => {
for (let i = 0; i < results.length; i++)
{
createP(results[i].word);
createImg(results[i].img);
}
})
.catch((err) => {})- when all these promises are complete and resolved, give me the results of those promises in an array in the same order as the original array
- all or nothing (you get the results at once or u get an error)
- so use a try catch