This question already has answers here:
How can I access the value of a promise?
(14 answers)
Async function returning promise, instead of value
(3 answers)
Closed 9 months ago.
I decided to create a special service aka ES6 class with needed functions to get data from API and then in index.js I could create an instance of the class and work with it. Unfortunately, when I try it, it always returns
Promise {<pending>}
and I don't really know what to do.
nytService.js:
export default class NYTService {
urlBase = "https://api.nytimes.com/svc/topstories/v2/";
category = "world";
apikey = *my api key* ;
async getNews(category = this.category) {
let url = `${this.urlBase}${category}.json?api-key=${this.apikey}`;
let res = await fetch(url)
let data = await res.json();
return data;
}
}
index.js:
import NYTService from "../services/nytService.js";
let nytService = new NYTService();
async function getNewsFinally() {
let res = await nytService.getNews();
return res;
}
console.log(getNewsFinally());
I did tried different things with the getNewsFinally function, did various .then chains, nothing helped
See if this tells you why:
async getNews(category = this.category) {
let url = `${this.urlBase}${category}.json?api-key=${this.apikey}`;
try {
let res = await fetch(url)
if (!res.ok) {
return res.statusText;
}
return await res.json();
} catch(err) {
console.error(err);
throw new Error(err);
}
}
Related
This question already has an answer here:
Why does property access with await appear to result in `undefined` when the object is returned from an async function? [duplicate]
(1 answer)
Closed 25 days ago.
I just try to understand what is happening - why my async method is waiting for another async method only if the response is deconstructed?
So I have some example code:
Dummy promise
const psedoRequest = () => {
return new Promise(resolve => setTimeout(resolve, 2000, "resolved"));
}
Dummy method which is calling promise
const methodRequest = async() => {
let response = "";
let error = "";
try {
response = await psedoRequest();
} catch (e) {
error = e;
}
return { response, error };
}
Actual methods
const invalidMainMethod = async() => {
const results = await methodRequest().response;
console.log('Invalid', results)
// the same would be with:
// const response = await methodRequest().response;
// console.log('Invalid', response );
}
const validMainMethod = async() => {
let results = ""
const { response } = await methodRequest();
results = response;
console.log('Valid', results);
}
Console log returns:
Invalid undefined
Valid resolved
Why deconstructing actually works in that case - so it's waiting for a response while accessing directly .response is not?
I thought that deconstructing is some syntactic sugar.
const results = await methodRequest().response;
Property accessing has higher precedence than await so this:
Calls methodRequest
Gets a promise object
Reads response (which is undefined) from the promise
awaits undefined (which isn't a promise so has no significant effect)
Assigns undefined to results
Later the promise resolves.
You could get the desired effect by using parentheses to override precedence:
const results = (await methodRequest()).response;
const { response } = await methodRequest();
await has higher precedence than = so it awaits the promise first then assigns and deconstruction is done as part of assignment.
This is ambiguous (to humans) and doesn't mean what you think it means:
await methodRequest().response
Are you awaiting methodRequest()? Or are you awaiting the response property from what methodRequest() returns?
Be explicit:
const results = (await methodRequest()).response;
I see David was faster, but since I have already written my response here it is anyways:
The simple difference here is the syntax:
const response = await methodRequest().response;
This snippet awaits methodRequest().response
What you are expecting it to do is to await methodRequest() and then get the response.
const { response } = await methodRequest();
This awaits methodRequest() and then takes the response from it like this:
const response = (await methodRequest()).response
This question already has answers here:
How to return many Promises and wait for them all before doing other stuff
(6 answers)
Closed 2 years ago.
I am new to React JS. In my application I am facing a situation where I need to call an API multiple times with different url, like apiurl.com/abc, apiurl.com/xyz. These abc and xyz are stored in an array. Hence I wanted to use .map() to change the url to make multiple api calls. But in .map() async await wont work, so looking for some solutions if any. I have gone through few possible solution like with promises, but could not implement.
Here is my code:
export const someAction = () => async (dispatch, param) => {
let myArray = ["abc", "xyz"];
let id= "";
param1 = "someauthcode";
myArray.map((x) => {
id = x;
const myResponse = await loaders.myResponseApi(param1, id); *//This does not work as await should be in async call*
});
dispatch({ type: types.ARRAY_API, payload: myResponse });
}
So the idea is to make 2 api calls with apiurl.com/abc, apiurl.com/xyz. I have constructed the url (apiurl.com) in an different file.
Thanks in advance.
Turn your array into an array of promises and then use Promise.all
export const someAction = () => async(dispatch) => {
try {
const payload = await Promise.all(myArray.map(id => loaders.myResponseApi(param1,id)));
dispatch({type:types.ARRAY_API,payload});
} catch(err) {
// an error occurred in at least one of the promises
}
}
Instead of using .map() you can use a traditional for or while loop:
export const someAction = () => async (dispatch, param) => {
let myArray = ["abc", "xyz"];
let id= "";
param1 = "someauthcode";
let i = 0;
while (i < myArray.length) {
id = myArray[i];
const myResponse = await loaders.myResponseApi(param1, id);
// handle response here...
i++;
}
}
This question already has answers here:
Avoiding callback hell in promises using nodejs
(2 answers)
Closed 3 years ago.
I'm having a hard time to sequence my API calls. so I used then() chaining to sequence them in order. All the API and the refresh token are Promises/Async. It's working but is there a cleaner/fancier/shorter way to this without using async/await because my parent function is not async. I don't fully understand the behavior of .then() and async/await
Here is the code inside the parent function:
refreshToken().then(token => {
let request = {} //format request
return axios.post(`${youtubeUrl}/upload/youtube/v3/videos?access_token=${token}&part=contentDetails`, request) //upload video
})
.then(uploadResponse => {
let uploadResponse = {}; //format uploadResponse
refreshToken().then(token => { //refresh the token again
return axios.put(`${youtubeUrl}?access_token=${token}`, uploadResponse) //update existing video
})
.then(updateResponse => {
let updateResponse = {}; //format updateResponse
axios.post(`${BasePath}/v1/videos`, updateResponse, headers)
.then(postResponse => {
if (postResponse.data.response === 'success') {
return dispatch(receivePostsData(postResponse.data))
} else if (postResponse.data.response === 'failed') return dispatch(receivePostsData(postResponse.data))
})
})
})
.catch(error => {
return dispatch(receivePostsData(error))
})
With aysnc await you can convert your callback hell to this:
important notes are:
async keyword before the function allows to use await
To handle exceptions you need to use try catch block.
async function uploadToYoutube() {
try {
let token = await refreshToken();
let request = {}
const youtubeUploadResponse = await axios.post(`${youtubeUrl}/upload/youtube/v3/videos?access_token=${token}&part=contentDetails`, request);
let uploadResponse = {};
token = await refreshToken();
const youtubeUpdateResponse = await axios.put(`${youtubeUrl}?access_token=${token}`, uploadResponse);
let updateResponse = {};
let postResponse = await axios.post(`${BasePath}/v1/videos`, updateResponse, headers);
if (postResponse.data.response === 'success') {
return dispatch(receivePostsData(postResponse.data))
} else if (postResponse.data.response === 'failed') {
//??? why do you here act like a success?
return dispatch(receivePostsData(postResponse.data))
}
} catch (error) {
//??? why do you here act like a success?
return dispatch(receivePostsData(error))
}
}
If you are using ES6 and above you can use async await
This question already has answers here:
Async/Await Class Constructor
(20 answers)
Can async/await be used in constructors?
(4 answers)
Closed 3 years ago.
The keyword await makes JavaScript wait until that promise settles and returns its result.
I noticed its possible to await a function
var neonlight = await neon();
Is it possible to await a class?
Example
var neonlight = await new Neon(neon_gas);
Technically .. Yes, If the constructor returns a Promise and as long as the await is inside an async function, here's an example ( might not be the best, actually it's a bad practice to have a constructor function return a Promise , but it's just to get this to work ):
class Test {
constructor() {
return new Promise((res, rej) => {
this.getData().then(({userId, title}) => {
this.userId = userId;
this.title = title;
res(this);
});
});
}
getData(){
return fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
}
greet(){
console.log('hello');
}
}
(async() => {
const x = await new Test();
console.log(x.userId, ' : ', x.title);
})();
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I want to get a "value of Data" from Firebase Realtime Database. You can find my code below:
async function getName() {
const result = await firebase.database().ref('/users/' + user.user.uid)
.once('value').
then(async function(snapshot) {
console.log("SNapshot =>");
console.log(snapshot.val().displayName); // returns "John Doe"
const result2 = await snapshot.val().displayName;
return result2;
});
return result; // returns "Promise Object"
};
It returns "Promise". But i want to get value not promise.
How should i fix my code?
Thanks.
You are mixing up use of async/await with then()/catch(). You should pick one syntax or the other, not both together in this case. You are also trying to use await on something that is not a promise. Just write your function like this:
async function getName() {
const snapshot = await firebase.database().ref('/users/' + user.user.uid).once('value')
return snapshot.val().displayName
}
And call it like this:
const name = await getName()
The getname function is doing async operation so you can do:
try {
await result = getName();
} catch (e) {
throw e;
}
within an async function, or, if you prefer without async :
result.then((res) => console.log(res));