How to translate Promise code to async await - javascript

I have some simple Promise in js:
let link = "https://jsonplaceholder.typicode.com/posts/1";
fetch(link)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
... and I want to translate it to 'async await' like here:
const API_ENDPOINT = 'https://jsonplaceholder.typicode.com/posts/1';
const fetchUsers = async () => {
const response = await fetch(API_ENDPOINT);
const data = await response.json();
};
... but I don't know how involve it in 'async await' correctly. This involving gives error:
fetchUsers()
.then(response => response.json())
.then (data => console.log(data))
.catch(error => console.error(`ERROR ${error}`));
Can you help me fix this error?

const API_ENDPOINT = 'https://jsonplaceholder.typicode.com/posts/1';
const fetchUsers = async () => {
const response = await fetch(API_ENDPOINT);
const data = await response.json();
console.log(data);
};
Your code is working prefectly Just call fetchUsers() and It will print data through this line console.log(data);
You can't use await keyword outside the async type function
Read this -
An async function can contain an await expression that pauses the
execution of the async function and waits for the passed Promise's
resolution, and then resumes the async function's execution and
returns the resolved value.
Remember, the await keyword is only valid inside async functions. If
you use it outside of an async function's body, you will get a
SyntaxError.

Two problems here;
You don't return anything from your async function
You apply response.json() twice.
Just corect the code as;
const API_ENDPOINT = 'https://jsonplaceholder.typicode.com/posts/1',
fetchUsers = async () => { var response = await fetch(API_ENDPOINT);
return await response.json();
};
fetchUsers().then (data => console.log(data))
.catch(error => console.error(`ERROR ${error}`));

Async functions must be functions. So, you need to create a function to do that.
MDN says:
The async function declaration defines an asynchronous function, which returns an AsyncFunction object.
Read more about that on MDN
So:
Create a function using the async keyword
Perform your fetch call inside the function using the await keyword
Perform any other operations inside your function using the await keyword around any promise related operations (if you want)
An example below:
async function doFetch(link) {
let result = await fetch(link); // this will wait the result to be fetched
console.log(result); // this will only log the result of the fetch promise after it is resolved
let json = await result.json();
console.log(json);
}
const link = 'https://jsonplaceholder.typicode.com/posts/1';
doFetch(link);
Also, remember that when you use the await keyword, your asynchronous code will actually run synchronously, so, two sequential calls to any promises will run synchronously, like so:
async function foo() {
let bar = await fetch('https://www.google.com');
// the line below will run just _*AFTER*_ the above line is completely resolved
let baz = await fetch('https://www.facebook.com');
}

Related

JavaScript, async await is returning a promise instead of the result

I have the below function. Why am I getting Promise { <state>: "pending" } when calling GetProfile("username")? What should I do?
const GetProfile = async (username) => {
await fetch(`${host}/api/v1/getprofile/${username}`).then((resp) => {
console.log(resp.json());
});
};
resp.json() returns a Promise and that's what you are console logging. It should resolve before getting the actual data. Since you are in an async function, you could do as below. Notice there is no need to have this then block you have.
const GetProfile = async (username) => {
const res = await fetch(`${host}/api/v1/getprofile/${username}`);
const data = await res.json();
return data;
});
};
That's normal async function behavior in javascript, they return promises.
In React, you can keep the value in a state.
const [profile,setProfile]=useState(null)
useEffect(()=> {
const GetProfile = async (username) => {
const profile = await fetch(`${host}/api/v1/getprofile/${username}`).then(resp => resp.json());
setProfile(profile)}
GetProfile(username);
},[username])
By default async function always returns promise. What you need to do is to execute it with await and you can extract the result, or chain it with then and move on.
I made an example with await:
const GetProfile = async (username) => {
await fetch(`${host}/api/v1/getprofile/${username}`).then((resp) => {
console.log(resp.json());
return resp.json()
});
};
const result = await GetProfile()
console.log(result);
NOTE:
You need to return resp.json() back from one of thens to see the result.
Because you're using .then after your async call, and resp.json() also returns a Promise which isn't being returned by your .then() call.
What happens in your case is:
const response = await fetch(`${host}/api/v1/getprofile/${username}`)
return response.json();
And because the json() function is a Promise itself (which isn't await'ed), the read of the json() call is the 'Pending' Promise that you're getting.
So to solve this, try either:
await fetch(`${host}/api/v1/getprofile/${username}`).then((resp) => resp.json())
or
const response = await fetch(`${host}/api/v1/getprofile/${username}`)
return await response.json();

Axios console.log data but return Promise <pending>

I've trying to retrieve the data, but I can't return it, can only see it in the console,
it's a simple axios get function but for some reason, I keep getting Promise even after using async/await.
my goal is to save the data to the memory.
any help would really be appreciated
let fetchTodo = async () => {
await axios.get('https://jsonplaceholder.typicode.com/todos/1')
.then(res => console.log(res.data))
.then(res => { return res })
.catch(err => console.log(err))
};
console.log("TEST: ", fetchTodo())
console
Asycn function always returns a promise, to get data from the fetchTodo function you need to create another async function which will await the result returned by fetchTodo(). if you are using react, you can use states and update the state while you are inside the .then chain of the fetchTodo function.
Asycn function always returns a promise. For getting or saving data you need to get it from .then() function. Here you can check the example. Hope so it will help you.
let fetchTodo = async () => {
await axios.get('https://jsonplaceholder.typicode.com/todos/1')
.then(res => console.log(res.data))
.then(res => {
// here you can performance your task, save data, send
// response or anything else
return res
})
.catch(err => console.log(err))
};
fetchTodo()
The async/await syntax means a function will return a Promise.
If you want to return the value, you could do something like this:
let fetchTodo = async () => {
try {
const res = await axios.get("https://jsonplaceholder.typicode.com/todos/1");
return res;
} catch (error) {
console.log(error);
}
};
// For the folowing code to work, it must be placed inside a async function as well
const res = await fetchTodo();
console.log(`Test: ${res.data}`);
// If it's a Top level call, use the folowing code
const res = fetchTodo().then( res => {
const data = res.data;
// The rest of your code goes here.
// ...
// ...
// ...
}).catch( error => {
console.log(error);
});
Some more information about it on: How can I use async/await at the top level?

JavaScript, Promise {<pending>}

async function db(path){
const res = await fetch('data.json');
const data = await res.json();
return data[path];
}
console.log(db("name"));
how can i fix the Promise {pending}
I am trying to get Global Access to my database json file from anywhere in my code is this right way or there is a better way ?
The problem is that you have an async function that returns a promise, but you call it in a not async way. What you should simply do is add an await before your call:
async function db(path){
const res = await fetch('data.json');
const data = await res.json();
return data[path];
}
console.log(await db("name"));
The return of the function simply returns another promise. So you can modify your function like this-
async function db(){
const res = await fetch('data.json');
const data = await res.json();
return data;
}
db().then(data => console.log(data['name']);
Note: You should not return anything from a async function. You should do what you want inside the funciton

await Promise.all not waiting despite async wrapper

Even after reading several answers to similar questions (e.g. this and that) I unfortunately still do not understand, why this code does not await the promises and hence logs ['check2'] last after the other checkpoints.
This is a minimal example using code from this guide. In the original code I need to fetch some Information from different sources before my express server can start listening.
console.log("check1");
const resolveInTwoSeconds = () => {
return new Promise((resolve) => {
setTimeout(() => resolve("check2"), 2000);
})
};
async function test() {
const asyncFunctions = [
resolveInTwoSeconds()
];
const results = await Promise.all(asyncFunctions);
console.log(results);
}
(async() => await test())();
console.log("check3");
EDIT:
Imagine "check3" to be a lot of code that is depended on the sideeffects of test().
Thus I want it to run after check2 was printed.
However I am using await here so I do not have to change or move "check3".
This line of code declares an async function and executes it:
(async() => await test())();
So far nothing waits for its result and the execution goes on to console.log("check3").
You have to explicitly wait for it:
await (async () => await test())();
Now, this won't work yet, because the top-level function is not async. Whenever you need to call await, you have to make sure it's called inside an async function. One way to do this would be to wrap everything inside another async function:
(async () => {
console.log("check1");
const resolveInTwoSeconds = () => {
return new Promise((resolve) => {
setTimeout(() => resolve("check2"), 2000);
})
};
async function test() {
const asyncFunctions = [
resolveInTwoSeconds()
];
const results = await Promise.all(asyncFunctions);
console.log(results);
}
await (async ()=> await test())();
console.log("check3");
})()
Otherwise, move your check3 into an async function you already have, as others suggested.
This should do what you want. you need the console.log to be inside the async function.
console.log("check1");
const resolveInTwoSeconds = () => {
return new Promise((resolve) => {
setTimeout(() => resolve("check2"), 2000);
})
};
async function test() {
const asyncFunctions = [
resolveInTwoSeconds()
];
const results = await Promise.all(asyncFunctions);
console.log(results);
}
(async() =>{
await test();
console.log("check3");
})();

Is it possible to use await outside async function

This is my simple function in nodejs
const myFunction = async() => {
const exercises = await Exercise.find({ workoutId })
return exercises
}
const value = await myFunction()
But when I do await outside async function it throws an error
await is a reserved word
Now how do I wait for the value outside the async function? Do I need to use callback or .then? Then what is the use async and await?
You can't use await outside an async function.
one trick to 'bypass' this limit is to use async IFEE:
const myFunction = async() => {
const exercises = await Exercise.find({ workoutId })
return exercises
};
(async () => {
const value = await myFunction()
})()
Short answer to the main question: "Is it possible to use await outside async function" no.
But there's multiple ways to access the value of an async operation, for example
const myFunction = async() => {
const exercises = await Exercise.find({ workoutId })
return exercises
}
const execution = () => {
myFunction().then( ( exercises ) => {
console.log( exercises );
});
}
As async is a wrapper for Promises to access the result you need to use then and when the execution is completed that callback is fired.

Categories