I'm in the process of converting some functions to async await and need help to solve an error.
Before
const getRequest = (url, headers) => {
return new Promise((resolve, reject) => {
axios.get(url, { headers })
.then((res) => {
return resolve(res);
})
.catch((err) => {
return reject(err);
});
});
After
async function getRequest(url, headers) {
return new Promise(resolve, reject) {
try {
const res = await axios.get(url, { headers })
return resolve(res);
}
catch(err){
return reject(err);
};
};
};
I'm getting an error when running the new code, any help would be appreciated.
First of all, your original code is badly indented, so let's fix that:
const getRequest = (url, headers) => {
return new Promise((resolve, reject) => {
axios.get(url, { headers })
.then((res) => {
return resolve(res);
})
.catch((err) => {
return reject(err);
});
});
Secondly, your original code contains a whole lot of unnecessary code because axios.get is already a promise. This shows lack of understanding on how promises work, please read this list of anti-patterns. You should just return the promise directly. Fixing that:
const getRequest = (url, headers) => {
return axios.get(url, { headers });
});
Thirdly, converting a function to async, when the function already returns a promise, means nothing more than simply adding the async keyword itself. You do not have to do anything to the function. Final result:
const getRequest = async (url, headers) => {
return axios.get(url, { headers });
});
async function getRequest(url, headers) {
const res = await axios.get(url, { headers })
return res;
};
First of all you have got a syntax error in declaring a promise.
The getRequest function should look something like this -
async function getRequest(url, headers) {
return new Promise((resolve, reject) => {
try {
const res = await axios.get(url, { headers })
return resolve(res);
}
catch (err) {
return reject(err);
};
});
};
Second, id axios.get(url, { headers }) is waiatable, you do not need to return a promise from the parent funtion.
You can simply return await axios.get(url, { headers });
async function getRequest(url, headers) {
return await axios.get(url, { headers });
};
Example
async function parent() {
console.log(await child(true));
}
function child(data) {
return new Promise((resolve, reject) => {
if (!!data) {
resolve("resolved!");
} else {
reject("rejected!");
}
});
}
parent();
Related
let companyInfo: PublicCompanyAPIResponseType;
companyInfo = await get<PublicCompanyAPIResponseType>({
url: getCompanyDataURL,
}).catch(res => {
responseStatus = res.status;
});
When i assign companyInfo variable to that get func
export async function get<T>({ url, headers }: ApiConnectSet): Promise<T> {
return new Promise((resolve, reject) => {
fetch(url, {
method: 'GET',
credentials: 'same-origin',
headers: headers,
})
.then(async res => {
if (res.ok) {
return resolve((await res.json()) as Promise<T>);
} else if (res.status === 401) {
const redirectPath = window.location.pathname;
window.location.href =
'/login?redirectPath=' + redirectPath;
} else {
reject(res);
}
})
.catch(error => {
reject(error);
});
});
}
Visual studio code shows this error
How can my get function only return PublicCompanyAPIResponseType?
try this, if it works
let companyInfo: PublicCompanyAPIResponseType;
try {
companyInfo = await get<PublicCompanyAPIResponseType>({
url: getCompanyDataURL,
})
} catch(err => {
// get the status from error object and assign it to response status
responseStatus = // your status code
});
Have you tried just adding the Promise<T> in the return statement?
export async function get<T>({ url, headers }: ApiConnectSet): Promise<T> {
return new Promise<T>((resolve, reject) => {
//your code
}
);
I am trying to refactor this code using try-catch blocks:
export const authorizeConnectyCube = async (accessToken) => {
const userCredentials = {
provider: 'firebase_phone',
'firebase_phone[project_id]': "xxxxxxxx",
'firebase_phone[access_token]': accessToken,
};
await createSession();
return new Promise((resolve, reject) => {
ConnectyCube.login(userCredentials, (error, user) => {
user ? resolve(user) : reject(error);
})
}).catch(error => console.log(error));
}
const createSession = () => {
return new Promise((resolve, reject) => {
ConnectyCube.createSession((error, session) => {
session ? resolve(session.user) : reject(error)
})
}).catch(error => console.log(error));
}
However I'm not getting the same result - the asynchronousity seems to be being handled differently. Here is my attempt at refactoring:
export const authorizeConnectyCube = async (accessToken) => {
const userCredentials = {
provider: 'firebase_phone',
'firebase_phone[project_id]': "xxxxxxxxxx",
'firebase_phone[access_token]': accessToken,
};
await createSession();
try {
ConnectyCube.login(userCredentials, (error, user) => {
return user;
})
}
catch (error) {
console.log(error)
}
}
const createSession = () => {
try {
ConnectyCube.createSession((error, session) => {
return session.user
})
} catch (error) {
console.log(error);
}
}
Is there any particular part of what I'm wrong? Thanks.
Callback-based APIs don't readily turn into something you can use for async/await (which under the hood uses promises). You'll have to "promisify" them first (i.e. wrap them in promises).
Here's an example of what I'm trying to say:
// Promisify these callback-based APIs.
const login = userCredentials => {
return new Promise((resolve, reject) => {
ConnectyCube.login(userCredentials, (error, user) => {
user ? resolve(user) : reject(error);
})
})
})
const createSession = () => {
return new Promise((resolve, reject) => {
ConnectyCube.createSession((error, session) => {
session ? resolve(session.user) : reject(error)
})
})
})
// Then use them in an async function
export const authorizeConnectyCube = async (accessToken) => {
const userCredentials = {
provider: 'firebase_phone',
'firebase_phone[project_id]': "xxxxxxxx",
'firebase_phone[access_token]': accessToken,
}
try {
await createSession()
return login(userCredentials)
} catch (e) {
console.warn(e)
}
}
Also, async functions return promises, with the resolved value being the return value, and the rejected value being any uncaught error thrown inside. A value wrapped in a promise as return value for an async function is redundant.
If you're using Node 8+, it has a utility called promisify which accepts a callback-based API and returns a promise-returning version of it.
My code is violating the eslint rule no-async-promise-executor but I'm not sure how to refactor it so that it doesn't have the async in the new Promise(async (resolve, reject) => {});. My code is full of these and I guess it causes errors to bot be caught so I could use some help understanding how to approach this better.
Here's an exampe function:
updateUser = () => {
return new Promise(async (resolve, reject) => {
try {
const url = "/getUser";
const response = await fetch(url);
if (response.ok) {
const user = await response.json();
//
// Do something with user object...
//
} else {
console.log("response", response);
window.location = "/admin";
}
resolve();
} catch (error) {
console.log("error: ", error);
reject(error);
}
});
};
when you mark the function as async, it will automatically wrap the return value inside a promise, whatever you return from the function... it will get passed to .then() and whatever is thrown inside a async function will get passed to your error handler such as .catch()
here is a example of what you could do.
const updateUser = async () => {
const url = "/getUser";
let response;
try {
response = await fetch(url);
} catch (error) {
throw new Error(error);
}
return response;
}
you can also reference the global promise explicit to return or reject values inside a async function.
const updateUser = async () => {
const url = "/getUser";
let response;
try {
response = await fetch(url);
} catch (error) {
Promise.reject(error);
}
return Promise.resolve(response);
}
async functions always return promises.
By wrapping your anonymous async function in new Promise(...) you are creating a Promise which only and always adopts the promise returned by the async function.
Just get rid of the wrapper, replace your resolve calls with return and your reject with throw.
updateUser = async () => {
try {
const url = "/getUser";
const response = await fetch(url);
if (response.ok) {
const user = await response.json();
//
// Do something with user object...
//
} else {
console.log("response", response);
window.location = "/admin";
}
} catch (error) {
console.log("error: ", error);
throw error;
}
};
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I am trying to store the actual response from a Promise to a variable
let token;
let tokenPromise = new Promise(function(resolve, reject) {
fetch(tokenUrl, options)
.then(res => {
if (res.ok) {
return res.json()
} else {
reject('Not clean')
}
}).then((data) => {
resolve(data.access_token)
})
})
token = tokenPromise.then(res => {return res})
return token
When this is run, token returns as the Promise object and not the actual response. How do I store the actual response or a value from the response as a variable within the parent function?
Because the function then returns a promise.
An alternative is to use an async function.
function getToken() {
let tokenPromise = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('myNewToken');
}, 100);
});
return tokenPromise;
}
async function main() {
let token = await getToken();
console.log(token);
}
main();
Why you create a new Promise around fetch?
function status(res) {
if (res.ok) {
return Promise.resolve(res)
} else {
return Promise.reject(new Error(res.statusText))
}
}
function json(res) {
return res.json()
}
function getToken() {
return fetch(tokenUrl, options) // Fetch URL
.then(status) // Is everything nice?
.then(json) // Response to json
.then(jsonData => jsonData.access_token) // return access_token
.catch(function(error) { // Some S*ht Happens :(
console.log('Request failed', error);
/* ErrorHandling Stuff */
});
}
You could use ES7 async/await
let token;
let tokenPromise = async () => {
try {
const res = await fetch(tokenUrl, options);
const data = await res.json();
return data.access_token
} catch (error) {
console.error('Error fetching token', error);
return 'Not clean';
}
}
token = tokenPromise().then(res => res);
return token;
I'd create a method called get token first.
Updated/simplified based off 4castle's suggestion
getToken() {
return fetch(tokenUrl, options)
.then(res => res.json())
.then(data => data.access_token)
}
Then inside the method you'd like to use the token
someMethod() {
getToken().then(token => {
// Use it.
})
}
I have response from my server like buildings : [record1, record2, ...] and I want to get only the array from that response. How can I get just the array from the Promise? I have tried some async/await things but I didn't understand how to use it in this code:
setupImpagination() {
....
fetch(pageOffset, pageSize, stats) {
return fetch(`http://localhost:3000/api/building/all?skip=${pageOffset}&limit=${pageSize}`)
.then(response => {
console.log('response.json() => ',response.json());
response.json()
})
.catch((error) => {
console.error(error);
});
}
});
}
.then way
fetch(pageOffset, pageSize, stats) {
return fetch(`http://localhost:3000/api/building/all?skip=${pageOffset}&limit=${pageSize}`)
.then(response => {
console.log('response.json() => ',response.json());
response.json()
}).then(responseJson => {
return responseJson.buildings
}).catch((error) => {
console.error(error);
});
}
});
async/await way:
async fetch(pageOffset, pageSize, stats) {
try {
const response = await fetch(`http://localhost:3000/api/building/all?skip=${pageOffset}&limit=${pageSize}`);
const responseJson = await response.json();
return responseJson.buildings;
} catch(error){
console.error(error);
}
async function fetchData (url, { type = 'json' } = {}) {
return await (await fetch(url))[type]();
}
// Example:
(async () => {
console.log(await fetchData('http://canskit.com', { type: 'text' }));
})();
As the original js on ES7, not aim at react-native