Chuyển tới nội dung
Home » Console Log Promise Pending | Introduction

Console Log Promise Pending | Introduction

#21 - Promise in JavaScript || Pending, Fulfilment and Reject States

async and await

The

async

keyword gives you a simpler way to work with asynchronous promise-based code. Adding

async

at the start of a function makes it an async function:


async function myFunction() { // This is an async function }

Inside an async function, you can use the

await

keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

This enables you to write code that uses asynchronous functions but looks like synchronous code. For example, we could use it to rewrite our fetch example:


async function fetchProducts() { try { // after this line, our function will wait for the `fetch()` call to be settled // the `fetch()` call will either return a Response or throw an error const response = await fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } // after this line, our function will wait for the `response.json()` call to be settled // the `response.json()` call will either return the parsed JSON object or throw an error const data = await response.json(); console.log(data[0].name); } catch (error) { console.error(`Could not get products: ${error}`); } } fetchProducts();

Here, we are calling

await fetch()

, and instead of getting a

Promise

, our caller gets back a fully complete

Response

object, just as if

fetch()

were a synchronous function!

We can even use a

try...catch

block for error handling, exactly as we would if the code were synchronous.

Note though that async functions always return a promise, so you can’t do something like:


async function fetchProducts() { try { const response = await fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } const data = await response.json(); return data; } catch (error) { console.error(`Could not get products: ${error}`); } } const promise = fetchProducts(); console.log(promise[0].name); // "promise" is a Promise object, so this will not work

Instead, you’d need to do something like:


async function fetchProducts() { try { const response = await fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } const data = await response.json(); return data; } catch (error) { console.error(`Could not get products: ${error}`); } } const promise = fetchProducts(); promise.then((data) => console.log(data[0].name));

Also, note that you can only use

await

inside an

async

function, unless your code is in a JavaScript module. That means you can’t do this in a normal script:


try { // using await outside an async function is only allowed in a module const response = await fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } const data = await response.json(); console.log(data[0].name); } catch (error) { console.error(`Could not get products: ${error}`); }

You’ll probably use

async

functions a lot where you might otherwise use promise chains, and they make working with promises much more intuitive.

Keep in mind that just like a promise chain,

await

forces asynchronous operations to be completed in series. This is necessary if the result of the next operation depends on the result of the last one, but if that’s not the case then something like

Promise.all()

will be more performant.

Introduction

Do you feel confuse when you read

new Promise()

,

.then()

, or

.catch()

? You are not alone, and I experience the same thing. Let’s start with reading the documentation itself.

According to MDN Web docs, “The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.”

#21 - Promise in JavaScript || Pending, Fulfilment and Reject States
#21 – Promise in JavaScript || Pending, Fulfilment and Reject States

Conclusion

I wish I can understand about promise in detail at first. It will be so helpful to read the chaining method. Other Promise Methods might be helpful in our code, and I might write them in another post. I hope this promise blog could help you to work around with promise.

How to use promises

Promises are the foundation of asynchronous programming in modern JavaScript. A promise is an object returned by an asynchronous function, which represents the current state of the operation. At the time the promise is returned to the caller, the operation often isn’t finished, but the promise object provides methods to handle the eventual success or failure of the operation.

Prerequisites: A reasonable understanding of JavaScript fundamentals, including event handling.
Objective: To understand how to use promises in JavaScript.

In the previous article, we talked about the use of callbacks to implement asynchronous functions. With that design, you call the asynchronous function, passing in your callback function. The function returns immediately and calls your callback when the operation is finished.

With a promise-based API, the asynchronous function starts the operation and returns a

Promise

object. You can then attach handlers to this promise object, and these handlers will be executed when the operation has succeeded or failed.

Supported Browsers:

The browsers supported by Async/Await Function are listed below:

  • Google Chrome 55 and above
  • Firefox 52 and above
  • Apple Safari 10.1 and above
  • Opera 42 and above
  • Edge 14 and above

JavaScript is best known for web page development but it is also used in a variety of non-browser environments. You can learn JavaScript from the ground up by following this JavaScript Tutorial and JavaScript Examples.

Whether you’re preparing for your first job interview or aiming to upskill in this ever-evolving tech landscape, GeeksforGeeks Courses are your key to success. We provide top-quality content at affordable prices, all geared towards accelerating your growth in a time-bound manner. Join the millions we’ve already empowered, and we’re here to do the same for you. Don’t miss out – check it out now!

Looking for a place to share your ideas, learn, and connect? Our Community portal is just the spot! Come join us and see what all the buzz is about!

Last Updated :
24 Nov, 2023

Like Article

Save Article

Share your thoughts in the comments

Please Login to comment…

This subreddit is for anyone who wants to learn JavaScript or help others do so. Questions and posts about frontend development in general are welcome, as are all posts pertaining to JavaScript on the backend.

Async Function Returns Promise

I’m trying to return an html string from an async function, but I keep getting “promise pending” returned.

async function getTemplateHtml() { const url = “http://localhost:8080/api/render”; const payload = [ { key1: “value1”, }, { key2: “value2”, }, ]; const response = await fetch(url, { method: “POST”, body: JSON.stringify(payload), headers: { “Content-Type”: “application/json” }, }); const json = await response.json(); return json; } const html = getTemplateHtml().then(function (json) { const { html } = json; console.log(“html”, html); return html; }); console.log(“getTemplateHtml”, html); //output “getTemplateHtml Promise { }”

I feel like I’m misunderstanding something fundamental about the JavaScript fetch API.

My ultimate goal here is to make a call to my PHP, get a response in JSON, and then do something in JavaScript when that response comes back. But I can’t get even a very stripped-down version to behave as I would expect. I’ve been looking at tutorials for hours, but I seem to be missing something crucial.

Here’s my index.php file, which generates two buttons:






This is the test.js file:


const btns = document.querySelectorAll('.btn'); function btnFunc() { output = asyncFunc() .then(response => console.log(response)); console.log(output); } async function asyncFunc() { const response = await fetch('/target.php'); return response.json(); } btns.forEach( btn => btn.addEventListener('click', btnFunc) );

And finally, this is target.php, which just sends back some JSON:



1, 'bar' => 2]);

What I would expect to be logged to the console is two instances of my JSON data. Instead, I’m getting this:


Promise {

: "pending" } Object { foo: 1, bar: 2 }

Why is the promise still pending when I’ve returned a response to it from

asyncFunc

? How can I get the JSON back out of the fetch request so I can work with it? I’ve been looking at tutorials, but they all seem to stop with logging it to the console inside the fetch function, and I feel like it’s the next step I’m missing.

Promises and async/await

Javascript is widely known for it’s asynchronous nature, meaning we differentiate between blocking code and non-blocking code. Promises exist to help you deal with non-blocking code in an effective way, on this page I will try to explain what they are and how to work with them. At the end of this post I’ll show some common promise problems and how to overcome them. Throughout this blogpost I’m assuming you’re familiar with general asynchronous programming concepts.

What are promises

A promise represents the eventual result of an asynchronous operation, so it basically provides a way to continue after an asynchronous operation.

Since the operation can obviously also fail a promise has 3 internal states.

  • pending: The promise is in it’s initial state, it has not completed it’s operation nor has it failed.

  • fulfilled: The operation has completed successfully.

  • rejected: The operation has failed.

In the browser API’s promises are also used, for example fetch returns a promise to return the result of a network request. When you start the request the promise is in it’s pending state. When the resource has returned successfully the promise changes to the fulfilled state, When it fails, for example when the server cannot be reached, the state becomes rejected.

How do they work

Besides using an API that returns a promise, there are several ways to create a promise, this is the most basic one:


const myPromise = new Promise((resolve, reject) => { doAsynchronousThings(() => { if(allIsGood) { resolve('my data') } else { reject(new Error('things failed')) } }) })

The new Promise call accepts a function which received 2 functions as arguments, the first resolves the promise and the second rejects it. A promise’s strength is it’s chainability, to continue when the promise is done (resolved or rejected) you can chain it with then(fulfilledFn, rejectedFn), catch(rejectedFn) or finally(fn), any of these returns a new promise which can be chained again.

then(fulfilledFn, rejectedFn)

Most of the time you will use then without the second argument but you can use it with either or both. You can use then to continue a promise chain when the previous promise has fulfilled.


myPromise.then(data => {


return doSomething(data)


})

The next part in the chain will receive whatever you return from this function.

catch(rejectedFn)

Used for when the promise has rejected, it is exactly the same as then(undefined, rejectedFn). When a promise is rejected it will find the next part in the chain that can handle the error, the rest is skipped. A catch handles the error so the chain can continue normally (unless you throw an error in the catch itself).


new Promise((resolve, reject) => reject()) .then(() => { // skipped }) .catch(err => { // handling error }) .then(() => { // executed })

finally(fn)

The finally call can be placed in the chain and will always run, it is however very different from the other two. The function you pass to finally receives no arguments and it’s return value is also not used. you can see the finally call as something that is in between the chain but does not alter it in any way with one exception, if you throw an error in it.

Promise chain

The promise flow basically works like the chart below.

It can sometimes be difficult how one progresses through a promise chain if you do not completely understand it so let’s play around with the different things that can happen.

Try to figure out what will be logged in the console for the following examples before checking in the console.

  1. example 1

  2. example 2

  3. example 3

  4. example 4

  5. example 5

Helper methods

There are several static helper methods on the Promise object.

Promise.resolve(data)

This is a shorthand for the following.


new Promise(resolve => resolve(data))

Promise.reject(data)

Basically the same as the previous one but with a rejected promise.


new Promise((resolve, reject) => reject(data))

Promise.all(iterable)

This will create a promise that will resolve if all the promises that are passed are resolved. You can pass promises or any other data, data not wrapped in a promise will act like an immediately resolved promise.

When the promise.all resolves because all of it’s arguments have resolved it will pass the data as an array to the next chain part.


Promise.all([ Promise.resolve(1), 2, Promise.resolve(3), ]).then(data => { console.log(data) // [1, 2, 3] })

If one of the passed promises rejects the promise.all is immediately rejected with the corresponding error, the result of the other promises are ignored.


Promise.all([ Promise.resolve(1), 2, Promise.reject(3), ]).catch(err => { console.log(err) // 3 })

Promise.race(iterable)

This will create a promise that will resolve or reject with the first promise that does. If already resolved/rejected promises or data are passed it will settle with the first value that does.

Unwrapping

When a promise returns data, that data will never be a promise itself. if the data returned from a promise would also be a promise then it will wait for that promise as well.


new Promise(resolve => { resolve(new Promise(innerResolve => innerResolve(3)) }).then(data => { console.log(data) // 3, not a promise wrapping the value 3 })

Promise syntax can be problematic

When doing certain things with promises you find they can be annoying to deal with, for example when you need variables from previous promises.


promise1() .then(value1 => { // do something return promise2(value1) .then(value2 => { // do something return promise3(value1, value2) }) })

Normally we would like promise3 to be executed in a toplevel .then, in this case that would not be easily doable because to execute promise3, we need value1 and value2 which are both gotten from promises. The problem is that you can only return a single value in a promise, you could fix this using a Promise.all but the readability would suffer just as it does right now.

Promises can also be difficult to deal with when the flow of the promise chain you are trying to create can go a different way depending on the returned data. To create an if/else structure you will need to create nested promises, this can get out of hand rather quickly.


promise1() .then(value1 => { if (value1 === 3) { return value1 } else if (value1 > 3) { return promise2(value1) .then(value2 => { if (value2 === value1) { return promise3(value2) .then(value3 => transform(value3)) .catch(() => true) .finally(() => console.log('did a thing')) } else { return true } }) } return promise4(value1) .then(value4 => { return promise3(value1, value4) }) }).catch(err => { console.error(err) })

async/await

To resolve the previous problems a new feature was added in the spec of ES2017, async/await. This is merely syntax sugar for things we already did with promises but it can add a lot to readability and brevity. The basic concept is to make asynchronous promise code read like synchronous code. Two keywords are added to make this possible, async and await.


async function init() { await new Promise(resolve(1)) await new Promise(resolve(2)) } init()

async

This is a keyword you place before a function you are creating, it will make the function return a promise. The value returned from your function will be the resolved value. You can throw an error in the normal way to reject the promise.

await

This keyword you can only use in an async function, you can place it before a promise or data to wait for that statement before moving to the next part/line. As this is waiting on a statement instead of a function you can see that it will read more like synchronous code, just remember that it’s actually not.

Since a promise unwraps its return value until it’s not a promise and async makes the function return a promise, it does not make sense to await your return value, so don’t use return await myPromise, just return it.

Fixing promise problems with async/await

If you rewrite the problem where you need variables from previous promises with async/await, you would get somethig like this:


async () => { const value1 = await promise1() const value2 = await promise2(value1) return promise3(value1, value2) }

You can do the same with the other problem where readability was suffering because of nested promises.


async () => { try { const value1 = await promise1() if (value1 === 3) { return value1 } else if (value1 > 3) { const value2 = await promise2(value1) if (value2 === value1) { try { const value3 = await promise3(value2) return transform(value3) } catch (err) { return true } finally { console.log('did a thing') } } else { return true } } const value4 = await promise4(value1) return promise3(value1, value4) } catch(err) { console.error(err) } }

This reads a lot easier since it looks more like synchronous code.

Common promise problems and tips & tricks
Call stack problem

Take the following example:


async () => { setTimeout(() => { throw new Error('bla') }, 1000) }

At first glance you might say that this would result in a rejected promise since the function in setTimeout is in a different call stack. That is not the case. The promise is resolved before the timeout is done and the error thrown will eventually be unhandled. To learn more about call stacks and why asynchronous code has a new call stack, I recommend watching this. In this case it would be more suited to use a normal promise because you can determine when the promise is done using the resolve and reject callbacks.


() => new Promise((resolve, reject) => { setTimeout(() => { reject(new Error('bla')) }, 1000) })

Slow awaits

So you have this code:


async () => { const a = await promise1() const b = await promise2() const c = await promise3() const d = await promise4() return a + b + c + d }

These promises that you are awaiting here have no reason to be waiting for each other and should run in parallel without a problem. To fix this you can wrap the promises in a Promise.all and await the result from that.


async () => { const [a, b, c, d] = await Promise.all([ promise1(), promise2(), promise3(), promise4(), ]) return a + b + c + d }

Mixing promises with async/await

You can mix promises with async/await without a problem and this can lead to some interesting solutions. One example of this would be to make the execution function of a new Promise call async, that way you can write the code inside with awaits for readability and you can use the resolve/reject callbacks for more control.


new Promise(async resolve => { await doStuff() await doOtherStuff() setTimeout(() => { resolve() }, 1000) })

Dit blog is geschreven door de specialisten van ISAAC.

Inmiddels is ISAAC onderdeel van iO. Meer weten? Neem gerust contact op!

How to get return the value from a promise?

const getUsers = async() => { const url = “www.google.com/user”; const response = await fetch(url); const data = await response.json return data[0].user }) } const data = getUsers().then(res => { console.log(res); // getting a value return res }); console.log(data) => // not getting any value except for Promise pending I tried const data = getUsers().then((res) => res); // // not getting any value either

Is there a way to only get the resolved response of getUsers so other functions can call the the function to return a response only? Thanks!

Here is my code:

Blockquote


router.get("test", async ctx => {
let q = await ctx.db
.execute(`SELECT w.create_time as create_time,w.camera_id,w.status,
w.problem_type_id,w.repair_user_id,w.no as no,wp.pic_url
FROM work_flow w
left OUTER
JOIN work_flow_pic wp ON w.no=wp.flow_id`);
let data = q.map(item => {
let url = ctx.db.execute(
`select * from work_flow_pic where flow_id=${item.no}`
);
return {
create_time: item.create_time,
no: item.no,
url: url.then(function(result) {
result;
})
};
});
console.log(data);
let retstr = `[{"ret":"0"}]`;
await ctx.render("interface_ret", {
retstr
});
});

When I run the code I get this output:

Blockquote


[ { create_time: 2018-10-09T02:47:54.000Z,
no: '153905327352986',
url: Promise { } },
{ create_time: 2018-10-09T02:47:54.000Z,
no: '153905327352986',
url: Promise { } },
{ create_time: 2018-10-09T08:51:33.000Z,
no: '153905327352987',
url: Promise { } } ]

I don’t know how to solve it

Layer
2

You can try this:


url: url.then(function(result) {
return result;
})

Seems weird to me, but since you return nothing from the anonymous function

url

result as a pending Promise i guess^^


function(result) {
result;
}

Will be call in another stack, it just a callback which will execute in the future.
And

.then

will return a promise as designed.

Something like this happen when you call

url.then(callback)


  • url

    is a promise,

    .then

    use to register callback to event loop. => “if you done that, execute the

    callback

    “.
  • ok! Now you (

    then

    ) end your job. Return another promise.

With .then or async await.

Looks like you are not waiting for your promises to be settled. Try that:


let data = await Promise.all(q.map(async item => {
let url = ctx.db.execute(
`select * from work_flow_pic where flow_id=${item.no}`
);
return {
create_time: item.create_time,
no: item.no,
url: await url
};
}));

You are using Promise.all ? Are you have multiply promises ?

q is an array and since there’s asynchronous code being executed inside each values’ callback you should wait till all of them finish.

JavaScript : Why is my asynchronous function returning Promise { pending } instead of a value?
JavaScript : Why is my asynchronous function returning Promise { pending } instead of a value?

The promise will always log pending as long as its results are not resolved yet. You must call

.then

on the promise to capture the results regardless of the promise state (resolved or still pending):


let AuthUser = function(data) {
return google.login(data.username, data.password).then(token => { return token } )
}
let userToken = AuthUser(data)
console.log(userToken) // Promise { }
userToken.then(function(result) {
console.log(result) // "Some User token"
})

Why is that?

Promises are forward direction only; You can only resolve them once. The resolved value of a

Promise

is passed to its

.then

or

.catch

methods.

Details

According to the Promises/A+ spec:

The promise resolution procedure is an abstract operation taking as
input a promise and a value, which we denote as [[Resolve]](promise,
x). If x is a thenable, it attempts to make promise adopt the state of
x, under the assumption that x behaves at least somewhat like a
promise. Otherwise, it fulfills promise with the value x.

This treatment of thenables allows promise implementations to
interoperate, as long as they expose a Promises/A+-compliant then
method. It also allows Promises/A+ implementations to “assimilate”
nonconformant implementations with reasonable then methods.

This spec is a little hard to parse, so let’s break it down. The rule is:

If the function in the

.then

handler returns a value, then the

Promise

resolves with that value. If the handler returns another

Promise

, then the original

Promise

resolves with the resolved value of the chained

Promise

. The next

.then

handler will always contain the resolved value of the chained promise returned in the preceding

.then

.

The way it actually works is described below in more detail:

1. The return of the

.then

function will be the resolved value of the promise.


function initPromise() {
return new Promise(function(res, rej) {
res("initResolve");
})
}
initPromise()
.then(function(result) {
console.log(result); // "initResolve"
return "normalReturn";
})
.then(function(result) {
console.log(result); // "normalReturn"
});

2. If the

.then

function returns a

Promise

, then the resolved value of that chained promise is passed to the following

.then

.


function initPromise() {
return new Promise(function(res, rej) {
res("initResolve");
})
}
initPromise()
.then(function(result) {
console.log(result); // "initResolve"
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve("secondPromise");
}, 1000)
})
})
.then(function(result) {
console.log(result); // "secondPromise"
});

Async / Await returning Promise instead of values

See original GitHub issue

Hi,

There seems to be an issue with Async/Await handling. Code below:


async function getData() { console.log('logging'); const test = await CSVToJSON().fromFile('./data/hans-puns.csv'); return test; }


const data = getData();

console logging data shows a Promise

Issue Analytics

  • State:
  • Created 5 years ago
  • Reactions:21
  • Comments:21
Top GitHub Comments

I think I might have been unclear in my earlier comment. I never wanted you to try to

await

outside an

async

function. You can’t do that in current Node. What you need to do is wrap your

await

call inside an

async

function, and then call that

async

function in the top-level of your script. If you just try to immediately use the output of the async function, it isn’t going to be useful, because it’s going to be a Promise. But I think people got the impression that I was suggesting to use the given code as-is but only adding await, which is not what I meant to say at all.

You’re trying to do something like this:


const data = asyncFunc(); console.log(data); // will give you something like Promise { }

You read my comment and understandably thought I meant to do this:


const data = await asyncFunc(); // will error console.log(data);

What I actually meant was to do this:


async function run() { const data = await asyncFunc(); console.log(data); // will print your data } run() // run the async function at the top-level, since top-level await is not currently supported in Node

You don’t need to await on the final

run()

call, since Node won’t exit until its event loop is empty.

async functions return promises. you need to do

const data = await getData()

– unless you intend to set

data

at the top level of the code, in which case you can’t await on

getData

and need to console.log from inside

getData

, or log from a different function that calls

await getData()

inside it.

Catching errors

This brings us to the last piece: how do we handle errors? The

fetch()

API can throw an error for many reasons (for example, because there was no network connectivity or the URL was malformed in some way) and we are throwing an error ourselves if the server returned an error.

In the last article, we saw that error handling can get very difficult with nested callbacks, making us handle errors at every nesting level.

To support error handling,

Promise

objects provide a

catch()

method. This is a lot like

then()

: you call it and pass in a handler function. However, while the handler passed to

then()

is called when the asynchronous operation succeeds, the handler passed to

catch()

is called when the asynchronous operation fails.

If you add

catch()

to the end of a promise chain, then it will be called when any of the asynchronous function calls fail. So you can implement an operation as several consecutive asynchronous function calls, and have a single place to handle all errors.

Try this version of our

fetch()

code. We’ve added an error handler using

catch()

, and also modified the URL so the request will fail.


const fetchPromise = fetch( "bad-scheme://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); fetchPromise .then((response) => { if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } return response.json(); }) .then((data) => { console.log(data[0].name); }) .catch((error) => { console.error(`Could not get products: ${error}`); });

Try running this version: you should see the error logged by our

catch()

handler.

Javascript Promises vs Async Await EXPLAINED (in 5 minutes)
Javascript Promises vs Async Await EXPLAINED (in 5 minutes)

What is Async Function ?

Async simply allows us to write promises-based code as if it was synchronous and it checks that we are not breaking the execution thread.

Async functions will always return a value. It makes sure that a promise is returned and if it is not returned then JavaScript automatically wraps it in a promise which is resolved with its value.

Example 1: In this example, we will see the basic use of async in JavaScript.

Using the fetch() API

Note: In this article, we will explore promises by copying code samples from the page into your browser’s JavaScript console. To set this up:

  1. open a browser tab and visit https://example.org
  2. in that tab, open the JavaScript console in your browser’s developer tools
  3. when we show an example, copy it into the console. You will have to reload the page each time you enter a new example, or the console will complain that you have redeclared

    fetchPromise

    .

In this example, we’ll download the JSON file from https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json, and log some information about it.

To do this, we’ll make an HTTP request to the server. In an HTTP request, we send a request message to a remote server, and it sends us back a response. In this case, we’ll send a request to get a JSON file from the server. Remember in the last article, where we made HTTP requests using the

XMLHttpRequest

API? Well, in this article, we’ll use the

fetch()

API, which is the modern, promise-based replacement for

XMLHttpRequest

.

Copy this into your browser’s JavaScript console:


const fetchPromise = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); console.log(fetchPromise); fetchPromise.then((response) => { console.log(`Received response: ${response.status}`); }); console.log("Started request…");

Here we are:

  1. calling the

    fetch()

    API, and assigning the return value to the

    fetchPromise

    variable
  2. immediately after, logging the

    fetchPromise

    variable. This should output something like:

    Promise {

    : "pending" }


    , telling us that we have a

    Promise

    object, and it has a

    state

    whose value is

    "pending"

    . The

    "pending"

    state means that the fetch operation is still going on.
  3. passing a handler function into the Promise’s

    then()

    method. When (and if) the fetch operation succeeds, the promise will call our handler, passing in a

    Response

    object, which contains the server’s response.
  4. logging a message that we have started the request.

The complete output should be something like:

Promise {

: “pending” } Started request… Received response: 200

Note that

Started request…

is logged before we receive the response. Unlike a synchronous function,

fetch()

returns while the request is still going on, enabling our program to stay responsive. The response shows the

200

(OK) status code, meaning that our request succeeded.

This probably seems a lot like the example in the last article, where we added event handlers to the

XMLHttpRequest

object. Instead of that, we’re passing a handler into the

then()

method of the returned promise.

Handle JavaScript Promises Like A Pro!
Handle JavaScript Promises Like A Pro!

javascript


const getData = async () => {


let data =


"Hello World"


return


data;


getData().then(data => console.log(data));

Promise Object States

A promise object has three states

pending

,

fulfilled

, and

rejected

. I will use an analogy here. Same as the name, Promise, it is similar to your friend who wants to make a promise to you. After he/she states a promise with you, the only thing that you can do is wait, right? Waiting is the

pending

state in JavaScript promise. In the end, you can find out if your friend will

fulfill

your promise or

reject

to keep his promise.

Understanding the Promise State Flow

When we create a promise object, at first, we will get a pending state. The promise state will be changed to be

fulfilled

if the function inside the promise calls the

resolve

callback. However, if the function inside promise calls

reject

callback, the state will be changed to be

rejected

Try to run this code in your browser console to see how the promise state is changed from pending to fulfilled.


const newPromise = new Promise((resolve) => { setTimeout(() => resolve('Success'), 2000); }); console.log("[After promise initialization]", newPromise); setTimeout(() => console.log("[After resolve callback run]", newPromise), 2000);

NodeJS : Async Function returns Promise pending
NodeJS : Async Function returns Promise pending

Conclusion

Promises are the foundation of asynchronous programming in modern JavaScript. They make it easier to express and reason about sequences of asynchronous operations without deeply nested callbacks, and they support a style of error handling that is similar to the synchronous

try...catch

statement.

The

async

and

await

keywords make it easier to build an operation from a series of consecutive asynchronous function calls, avoiding the need to create explicit promise chains, and allowing you to write code that looks just like synchronous code.

Promises work in the latest versions of all modern browsers; the only place where promise support will be a problem is in Opera Mini and IE11 and earlier versions.

We didn’t touch on all features of promises in this article, just the most interesting and useful ones. As you start to learn more about promises, you’ll come across more features and techniques.

Many modern Web APIs are promise-based, including WebRTC, Web Audio API, Media Capture and Streams API, and many more.

In React development, handling asynchronous code is a fundamental skill. As we delve into the realm of promises in React, we must grasp how they enable us to manage asynchronous operations effectively. This introduction will lay the groundwork for understanding promises and their role in creating responsive and scalable applications.

Promises in JavaScript are a core concept that every developer should be familiar with, especially when dealing with asynchronous code. A new promise in JavaScript represents a value that may be available now, later, or never. It allows you to write asynchronous code that can wait for an operation to complete without blocking the execution of the rest of your code.

Here’s a simple example of creating a new promise:


1const newPromise = new Promise((resolve, reject) => { 2 // Asynchronous operation here 3 if (/* operation successful */) { 4 resolve('Success!'); 5 } else { 6 reject('Failure'); 7 } 8}); 9

In the above example, the newPromise is created with two parameters: resolve and reject. These are callback functions that determine the future state of the promise. When the asynchronous operation is successful, the resolve function is called, and the promise is fulfilled. Conversely, if the operation fails, the reject function is called, and the promise is rejected.

Promises are crucial in managing asynchronous operations in JavaScript and, by extension, in React applications. They provide a robust way to handle the outcome of asynchronous code, whether it’s the successful completion of a data fetching request or an error fetching data from an API.

Consider the following example where we make an API call using a promise:


1function fetchData() { 2 return new Promise((resolve, reject) => { 3 fetch('

') 4 .then(response => { 5 if (response.ok) { 6 return response.json(); 7 } 8 throw new Error('Error fetching data'); 9 }) 10 .then(data => resolve(data)) 11 .catch(error => reject(error)); 12 }); 13} 14 15fetchData().then(data => { 16 console.log('Data:', data); 17}).catch(error => { 18 console.error('Error:', error); 19}); 20

In the above example, fetchData returns a new promise that resolves with the data or rejects with an error message. The promise chain lets us handle the asynchronous data fetching operation cleanly and efficiently. When the promise resolves, the .then method is called with the resolved value, and when it rejects, the .catch method handles the error.

To start working with promises in React, we must first set up a proper development environment. This involves creating a new React application and installing the necessary libraries to help us handle promises more effectively.

While JavaScript’s native promise functionality is powerful, there are libraries available that can enhance the way we handle promises in a React application. One such library is axios, which is a popular HTTP client for making API calls and managing responses and errors more gracefully.

To install axios, run the following command in your project directory:


1npm install axios 2

Another useful library for managing asynchronous state in React components is react-query. It provides hooks for fetching, caching, and updating asynchronous data without managing complex state and effect logic.

To install react-query, use the following command:


1npm install react-query 2

With these libraries installed, you can now make API calls using axios and manage the asynchronous data with react-query’s powerful hooks. These tools will help you handle promises in your React app more effectively, leading to cleaner code and better performance.

Once the React environment is set up and the necessary libraries are installed, the next step is implementing promises within React components. This involves handling asynchronous data with state and understanding lifecycle methods versus hooks for managing promises.

In React, the state keeps track of data that can change over time. It’s essential to handle the data statefully when dealing with asynchronous operations, such as API calls. The useState hook is a fundamental tool for managing state in function components.

Here’s an example of how to use state to handle asynchronous data from an API call:


1import React, { useState, useEffect } from 'react'; 2import axios from 'axios'; 3 4function DataFetchingComponent() { 5 const [data, setData] = useState(null); 6 const [loading, setLoading] = useState(true); 7 const [error, setError] = useState(null); 8 9 useEffect(() => { 10 axios.get('

') 11 .then(response => { 12 setData(response.data); 13 setLoading(false); 14 }) 15 .catch(error => { 16 setError(error); 17 setLoading(false); 18 }); 19 }, []); // Empty dependency array ensures this runs once on mount 20 21 if (loading) return

Loading...

; 22 if (error) return

Error: {error.message}

; 23 24 return ( 25

26

Data

27 {/* Render your data here */} 28

29 ); 30} 31

In the above code, the useState hook is used to create a data, loading, and error state. The useEffect hook is then used to perform the API call when the component mounts. The state is updated accordingly based on the result of the promise.

Before introducing hooks in React 16.8, lifecycle methods were the primary way to handle asynchronous operations in class components. ComponentDidMount, componentDidUpdate, and componentWillUnmount were used to execute code at specific points in a component’s lifecycle.

However, with the introduction of hooks, function components can now use useEffect to handle side effects, which include asynchronous operations. The useEffect hook can replicate the behavior of the lifecycle methods in a more concise and readable way.

Here’s an example of how you might have used lifecycle methods in a class component to handle promises:


1import React, { Component } from 'react'; 2import axios from 'axios'; 3 4class DataFetchingComponent extends Component { 5 state = { 6 data: null, 7 loading: true, 8 error: null 9 }; 10 11 componentDidMount() { 12 axios.get('

') 13 .then(response => { 14 this.setState({ data: response.data, loading: false }); 15 }) 16 .catch(error => { 17 this.setState({ error, loading: false }); 18 }); 19 } 20 21 render() { 22 const { data, loading, error } = this.state; 23 24 if (loading) return

Loading...

; 25 if (error) return

Error: {error.message}

; 26 27 return ( 28

29

Data

30 {/* Render your data here */} 31

32 ); 33 } 34} 35

While lifecycle methods are still valid and used in class components, hooks provide a more modern and often simpler way to handle promises in React function components. They allow for better code organization and reusability, making them a preferred choice for many developers when managing asynchronous operations.

When working with promises in React, handling errors gracefully is crucial. Errors can occur for various reasons, such as network issues, server problems, or bugs in the code. Proper error handling ensures that your application can respond to issues in a user-friendly manner and maintain stability.

The .catch method is an essential part of a promise chain, providing a way to handle errors that may occur during the execution of asynchronous code. When a promise is rejected, the .catch method is called with the error object, allowing developers to implement custom error-handling logic.

Here’s an example of using .catch in a React component:


1import React, { useState, useEffect } from 'react'; 2import axios from 'axios'; 3 4function DataFetchingComponent() { 5 const [data, setData] = useState(null); 6 const [error, setError] = useState(null); 7 8 useEffect(() => { 9 axios.get('

') 10 .then(response => { 11 setData(response.data); 12 }) 13 .catch(error => { 14 setError(error); 15 console.error('Error fetching data:', error); 16 }); 17 }, []); 18 19 if (error) return

Error: {error.message}

; 20 if (!data) return

Loading...

; 21 22 return ( 23

24

Data

25 {/* Render your data here */} 26

27 ); 28} 29

In the above code, the .catch method logs the error to the console and sets the error state, which can then display an error message to the user.

Error bounds are another helpful feature in React for handling errors. They are React components that detect JavaScript problems anywhere in their child component tree, log them, and display a fallback UI instead of the crashed component tree.

Here’s an example of an error boundary component:


1import React, { Component } from 'react'; 2 3class ErrorBoundary extends Component { 4 state = { hasError: false }; 5 6 static getDerivedStateFromError(error) { 7 // Update state so the next render will show the fallback UI. 8 return { hasError: true }; 9 } 10 11 componentDidCatch(error, errorInfo) { 12 // You can also log the error to an error reporting service 13 console.error('Error caught by Error Boundary:', error, errorInfo); 14 } 15 16 render() { 17 if (this.state.hasError) { 18 // You can render any custom fallback UI 19 return

Something went wrong.

; 20 } 21 22 return this.props.children; 23 } 24} 25

To use the error boundary, wrap it around any component that may throw an error:


1

2 3

4

With the error boundary in place, if DataFetchingComponent or any of its descendants throw an error, the error boundary will catch it, and the fallback UI will be displayed.

Implementing .catch for individual promises and using error boundaries are effective strategies for handling errors in React applications. They provide a safety net for catching and dealing with unexpected issues, ensuring your application remains robust and user-friendly.

When working with promises in React, several best practices can help ensure your code is reliable, maintainable, and efficient:

By following these best practices, developers can effectively harness the power of promises to build robust and responsive React applications that easily handle asynchronous operations. Promises are indispensable in the React developer’s toolkit, whether for simple data fetching or complex transactional processes.

Promises are a cornerstone of asynchronous programming in JavaScript, and understanding how to implement and handle them in React is essential for developing modern web applications.

By embracing the power of promises, you can create applications that are not only responsive and efficient but also maintainable and robust in the face of errors and unexpected behavior. Whether fetching data, coordinating complex operations, or managing asynchronous code, the patterns and practices discussed here will serve as a valuable guide.

JavaScript is Synchronous in nature which means that it has an event loop that allows you to queue up an action that won’t take place until the loop is available sometime after the code that queued the action has finished executing. But there are a lot of functionalities in our program that make our code Asynchronous and one of them is the Async/Await functionality.

Async/Await is the extension of promises that we get as support in the language.

javascript


const getData = async () => {


let y = await


"Hello World"


console.log(y);


console.log(1);


getData();


console.log(2);

Notice that the console prints 2 before the “Hello World”. This is due to the usage of the await keyword.

The

async

keyword transforms a regular JavaScript function into an asynchronous function, causing it to return a Promise.

The

await

keyword is used inside an async function to pause its execution and wait for a Promise to resolve before continuing.

Example 3: In this example, we will be implementing several promises in a method, and then that method we will use for displaying our result.

Debug Tips - finding an unresolved promise using console.log
Debug Tips – finding an unresolved promise using console.log

Chaining promises

With the

fetch()

API, once you get a

Response

object, you need to call another function to get the response data. In this case, we want to get the response data as JSON, so we would call the

json()

method of the

Response

object. It turns out that

json()

is also asynchronous. So this is a case where we have to call two successive asynchronous functions.

Try this:


const fetchPromise = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); fetchPromise.then((response) => { const jsonPromise = response.json(); jsonPromise.then((data) => { console.log(data[0].name); }); });

In this example, as before, we add a

then()

handler to the promise returned by

fetch()

. But this time, our handler calls

response.json()

, and then passes a new

then()

handler into the promise returned by

response.json()

.

This should log “baked beans” (the name of the first product listed in “products.json”).

But wait! Remember the last article, where we said that by calling a callback inside another callback, we got successively more nested levels of code? And we said that this “callback hell” made our code hard to understand? Isn’t this just the same, only with

then()

calls?

It is, of course. But the elegant feature of promises is that

then()

itself returns a promise, which will be completed with the result of the function passed to it. This means that we can (and certainly should) rewrite the above code like this:


const fetchPromise = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); fetchPromise .then((response) => response.json()) .then((data) => { console.log(data[0].name); });

Instead of calling the second

then()

inside the handler for the first

then()

, we can return the promise returned by

json()

, and call the second

then()

on that return value. This is called promise chaining and means we can avoid ever-increasing levels of indentation when we need to make consecutive asynchronous function calls.

Before we move on to the next step, there’s one more piece to add. We need to check that the server accepted and was able to handle the request, before we try to read it. We’ll do this by checking the status code in the response and throwing an error if it wasn’t “OK”:


const fetchPromise = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); fetchPromise .then((response) => { if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } return response.json(); }) .then((data) => { console.log(data[0].name); });

Javascript


function


asynchronous_operational_method() {


let first_promise =


new


Promise((resolve, reject) => resolve(


"Hello"


));


let second_promise =


new


Promise((resolve, reject) => {


setTimeout(() => {


resolve(


" GeeksforGeeks.."


);


}, 1000);


});


let combined_promise =


Promise.all([first_promise, second_promise]);


return


combined_promise;


async


function


display() {


let data = await asynchronous_operational_method();


console.log(data);


display();

Output:

[ ‘Hello’, ‘ GeeksforGeeks..’ ]

Javascript ES6 - Function Returning a Promise
Javascript ES6 – Function Returning a Promise

Promise terminology

Promises come with some quite specific terminology that it’s worth getting clear about.

First, a promise can be in one of three states:

  • pending: the promise has been created, and the asynchronous function it’s associated with has not succeeded or failed yet. This is the state your promise is in when it’s returned from a call to

    fetch()

    , and the request is still being made.
  • fulfilled: the asynchronous function has succeeded. When a promise is fulfilled, its

    then()

    handler is called.
  • rejected: the asynchronous function has failed. When a promise is rejected, its

    catch()

    handler is called.

Note that what “succeeded” or “failed” means here is up to the API in question. For example,

fetch()

rejects the returned promise if (among other reasons) a network error prevented the request being sent, but fulfills the promise if the server sent a response, even if the response was an error like 404 Not Found.

Sometimes, we use the term settled to cover both fulfilled and rejected.

A promise is resolved if it is settled, or if it has been “locked in” to follow the state of another promise.

The article Let’s talk about how to talk about promises gives a great explanation of the details of this terminology.

Promise Object Methods

After we understand the basic concept of promise states, we can move forward with promise methods. We just saw the state was changing from

pending

to

fulfilled

, but we didn’t access the result. That’s the reason why we need the promise methods.

If we take a look inside the promise prototype, we can find out that promise has a constructor method, and three prototype methods, which are

.then()

,

.catch()

,

.finally()

. Therefore, whenever you see those methods are being called, you can assume that the variable before the method is a promise object.

Constructor

The promise constructor requires a callback function to be sent as a parameter. The callback function has two function parameters, and the parameter name convention is

resolve

and

reject

.

resolve

function will cause the state change to be

fulfilled

. On the other hand,

reject

will change the state to be

rejected

. Both functions has one parameter to return the value.


const fulfilledPromise = new Promise((resolve, reject) => { resolve("Success") }); const rejectedPromise = new Promise((resolve, reject) => { reject("Fail") });

.then()

Alright, the most popular promise method. You probably see this method everywhere.

.then()

has two optional parameters that are

onFulfilled

and

onRejected

. I guess you can understand it easily. The first parameter will handle the result of the promise if the state is

fulfilled

, and the second parameter is for handling

rejected

state.


// ... newPromise.then( (fulfilledResult) => { console.log(fulfilledResult); }, (rejectedResult) => { console.log(rejectedResult); } );

— OR —


// ... function onFulfilled(result) { console.log(result); } function onRejected(error) { console.log(error); } newPromise.then(onFulfilled, onRejected);

In fact, in my experience, I don’t use the second parameter because we have another method to handle the

rejected

state, which we will discuss in the next section.

.catch()

With this method, the

rejected

state will directly be handled. It’s similar like

.then()

, but

.catch()

is only has one callback function parameter.


newPromise.catch((error) => { console.log(error); });

Example of chaining

.catch()

with

then()

.


// ... myPromise.then(result => console.log(result)) .catch(error => console.log(error));

.finally()

Finally, it is

.finally()

, the last promise object method.

.then()

same like

.catch

that it only has one callback function.In addition, It will be called when the promise is settled whether the state is

fulfilled

or

rejected

. However, the

.finally()

callback function doesn’t have any parameter.


// .. newPromise.finally(() => { console.log('Done'); });


.then()

,

.catch()

,

.finally()

, and Promise constructor return a promise object. That’s why you might see this chaining method.


fetch('https://api.zippopotam.us/us/90210') .then((res) => res.json()) .then((data) => console.log(data)) .catch((error) => console.log(error)) .finally(() => console.log('done'));

Converting callbacks to promises | Handle Promises using async/wait | node js tutorial
Converting callbacks to promises | Handle Promises using async/wait | node js tutorial

Async and Await

In the beginning, I was confused with

fetch()

. Why does

fetch

always need double

.then

like the previous example. After I read the fetch and response.json() documentation meticulously, I realized that those return promise objects as well. That’s why we need

.then()

There is another way if we don’t want to use chaining

.then()

. Thanks to async and await. In order to activate await, we must call await inside the async function. This is an example.


async function fetchData() { const response = await fetch('https://api.zippopotam.us/us/90210'); const data = await response.json(); }

If I translate to our language, await is like waiting for our friend to answer his promise. Therefore, using await we can get the answer before we execute the next line of code.

Try to run the first code snippet in your browser console, and compare it with the second code. The first code will return a promise, but in the second one, you can get the value.


async function fetchData() { const response = fetch('https://api.zippopotam.us/us/90210'); console.log(response); const data = response.json(); console.log(data); } fetchData();


async function fetchData2() { const response = await fetch('https://api.zippopotam.us/us/90210'); console.log(response); const data = await response.json(); console.log(data); } fetchData2();

Combining multiple promises

The promise chain is what you need when your operation consists of several asynchronous functions, and you need each one to complete before starting the next one. But there are other ways you might need to combine asynchronous function calls, and the

Promise

API provides some helpers for them.

Sometimes, you need all the promises to be fulfilled, but they don’t depend on each other. In a case like that, it’s much more efficient to start them all off together, then be notified when they have all fulfilled. The

Promise.all()

method is what you need here. It takes an array of promises and returns a single promise.

The promise returned by

Promise.all()

is:

  • fulfilled when and if all the promises in the array are fulfilled. In this case, the

    then()

    handler is called with an array of all the responses, in the same order that the promises were passed into

    all()

    .
  • rejected when and if any of the promises in the array are rejected. In this case, the

    catch()

    handler is called with the error thrown by the promise that rejected.

For example:


const fetchPromise1 = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); const fetchPromise2 = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/not-found", ); const fetchPromise3 = fetch( "https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json", ); Promise.all([fetchPromise1, fetchPromise2, fetchPromise3]) .then((responses) => { for (const response of responses) { console.log(`${response.url}: ${response.status}`); } }) .catch((error) => { console.error(`Failed to fetch: ${error}`); });

Here, we’re making three

fetch()

requests to three different URLs. If they all succeed, we will log the response status of each one. If any of them fail, then we’re logging the failure.

With the URLs we’ve provided, all the requests should be fulfilled, although for the second, the server will return

404

(Not Found) instead of

200

(OK) because the requested file does not exist. So the output should be:

https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json: 200 https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/not-found: 404 https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json: 200

If we try the same code with a badly formed URL, like this:


const fetchPromise1 = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); const fetchPromise2 = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/not-found", ); const fetchPromise3 = fetch( "bad-scheme://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json", ); Promise.all([fetchPromise1, fetchPromise2, fetchPromise3]) .then((responses) => { for (const response of responses) { console.log(`${response.url}: ${response.status}`); } }) .catch((error) => { console.error(`Failed to fetch: ${error}`); });

Then we can expect the

catch()

handler to run, and we should see something like:

Failed to fetch: TypeError: Failed to fetch

Sometimes, you might need any one of a set of promises to be fulfilled, and don’t care which one. In that case, you want

Promise.any()

. This is like

Promise.all()

, except that it is fulfilled as soon as any of the array of promises is fulfilled, or rejected if all of them are rejected:


const fetchPromise1 = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); const fetchPromise2 = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/not-found", ); const fetchPromise3 = fetch( "https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json", ); Promise.any([fetchPromise1, fetchPromise2, fetchPromise3]) .then((response) => { console.log(`${response.url}: ${response.status}`); }) .catch((error) => { console.error(`Failed to fetch: ${error}`); });

Note that in this case we can’t predict which fetch request will complete first.

These are just two of the extra

Promise

functions for combining multiple promises. To learn about the rest, see the

Promise

reference documentation.

The Dangers Of Promise.all()
The Dangers Of Promise.all()

Keywords searched by users: console log promise pending

Js Promises #2: How To Get Current Promise Status And Build Your Own Promise  Queue? - Dev Community
Js Promises #2: How To Get Current Promise Status And Build Your Own Promise Queue? – Dev Community
Promises In Javascript
Promises In Javascript
21 - Promise In Javascript || Pending, Fulfilment And Reject States -  Youtube
21 – Promise In Javascript || Pending, Fulfilment And Reject States – Youtube
Returning Data From Fetch Async Await Issue - Javascript - Codecademy Forums
Returning Data From Fetch Async Await Issue – Javascript – Codecademy Forums

See more here: kientrucannam.vn

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *