How release Promise pending with async-await in react - javascript

my Code :
const attList = async (areaCode, cityCode) => {
const url = `http://api.visitkorea.or.kr/openapi/service/rest/KorService/areaBasedList?ServiceKey=${serviceKey}&contentTypeId=12&areaCode=${areaCode}&numOfRows=40&sigunguCode=${cityCode}&MobileOS=ETC&MobileApp=AppTest`;
try {
const {data:res} = await axios.get(url)
const list = res.response.body.items.item;
return list
} catch (err) {
console.log(err);
}
}
console.log(attList(1, 1))
on Console :
PromiseResult is Allright, but I don't know how release PromiseResult from Promise{}

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise. Note: Even though the return value of an async function behaves as if it's wrapped in a Promise. resolve, they are not equivalent.
const attList = async (areaCode, cityCode, serviceKey) => {
const url = `http://api.visitkorea.or.kr/openapi/service/rest/KorService/areaBasedList?ServiceKey=${serviceKey}&contentTypeId=12&areaCode=${areaCode}&numOfRows=40&sigunguCode=${cityCode}&MobileOS=ETC&MobileApp=AppTest`;
const _url = 'https://jsonplaceholder.typicode.com/todos/1';
try {
const data = await axios.get(url);
console.log(data);
} catch (err) {
console.log(err);
}
};
attList(1, 1, null);
you didn't define serviceKey so I couldn't test it with your URL, but I assure you the syntax is just fine.

Related

Promise wont return valid value

I have this test I made just to check an API, but then i tryied to add an URL from a second fetch using as parameter a value obtained in the first fetch and then return a value to add in the first fecth. The idea is to add the image URL to the link. thanks in advance.
function script() {
const url = 'https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20'
const result = fetch(url)
.then( (res)=>{
if(res.ok) {
return res.json()
} else {
console.log("Error!!")
}
}).then( data => {
console.log(data)
const main = document.getElementById('main');
main.innerHTML=`<p><a href='${data.next}'>Next</a></p>`;
for(let i=0; i<data.results.length;i++){
main.innerHTML=main.innerHTML+`<p><a href=${getImageURL(data.results[i].url)}>${data.results[i].name}</a></p>`;
}
})
}
async function getImageURL(imgUrl) {
const resultImg = await fetch(imgUrl)
.then( (res)=> {
return res.json()
})
.then (data => {
console.log(data.sprites.other.dream_world.front_default);
})
return resultImg.sprites.other.dream_world.front_default;
}
In general, don't mix .then/.catch handlers with async/await. There's usually no need, and it can trip you up like this.
The problem is that your fulfillment handler (the .then callback) doesn't return anything, so the promise it creates is fulfilled with undefined.
You could return data, but really just don't use .then/.catch at all:
async function getImageURL(imgUrl) {
const res = await fetch(imgUrl);
if (!res.ok) {
throw new Error(`HTTP error ${res.status}`);
}
const resultImg = await res.json();
return resultImg.sprites.other.dream_world.front_default;
}
[Note I added a check of res.ok. This is (IMHO) a footgun in the fetch API, it doesn't reject its promise on HTTP errors (like 404 or 500), only on network errors. You have to check explicitly for HTTP errors. (I wrote it up on my anemic old blog here.)]
There's also a problem where you use getImageURL:
// Incorrent
for (let i = 0; i < data.results.length; i++) {
main.innerHTML=main.innerHTML+`<p><a href=${getImageURL(data.results[i].url)}>${data.results[i].name}</a></p>`;
}
The problen here is that getImageURL, like all async functions, returns a promise. You're trying to use it as those it returned the fulfillment value you're expecting, but it can't — it doesn't have that value yet.
Instead, you need to wait for the promise(s) youre creating in that loop to be fulfilled. Since that loop is in synchronous code (not an async function), we'd go back to .then/.catch, and since we want to wait for a group of things to finish that can be done in parallel, we'd do that with Promise.all:
// ...
const main = document.getElementById('main');
const html = `<p><a href='${data.next}'>Next</a></p>`;
Promise.all(data.results.map(async ({url, name}) => {
const realUrl = await getImageURL(url);
return `<p><a href=${realUrl}>${name}</a></p>`;
}))
.then(paragraphs => {
html += paragraphs.join("");
main.innerHTML = html;
})
.catch(error => {
// ...handle/report error...
});
For one, your
.then (data => {
console.log(//...
at the end of the promise chain returns undefined. Just remove it, and if you want to console.log it, do console.log(resultImg) in the next statement/next line, after await.
This the final version that accomplish my goal. Just want to leave this just in case someone finds it usefull. Thanks for those who answer!
function script() {
const url = 'https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20'
const result = fetch(url)
.then( (res)=>{
if(res.ok) {
return res.json()
} else {
console.log("Error!!")
}
}).then( data => {
console.log(data)
const main = document.getElementById('main');
main.innerHTML=`<p><a href='${data.next}'>Proxima Página</a></p>`;
Promise.all(data.results.map(async ({url, name}) => {
const realUrl = await getImageURL(url);
return `<div><a href=${realUrl}>${name}</a></div>`;
}))
.then(paragraphs => {
main.innerHTML=main.innerHTML+paragraphs;
})
.catch(error => {
console.log(error);
});
})
}
async function getImageURL(imgUrl) {
const res = await fetch(imgUrl);
if(!res.ok) {
throw new Error(`HTTP Error ${res.status}`)
}
const resultImg = await res.json();
return resultImg.sprites.other.dream_world.front_default
}

How to use async/await using crypto.randomBytes in nodejs?

const crypto = require('crypto');
async function getKey(byteSize) {
let key = await crypto.randomBytes(byteSize);
return key;
}
async function g() {
let key = await getKey(12);
return key;
}
console.log(g());
console.log('hello - want this called after g() above');
I've been at this for an hour and I can't understand how to ensure that I get a key using async/await. I get a Promise-pending no matter what I do.
I've also tried this:
async function getKey(byteSize) {
let key = await crypto.randomBytes(byteSize);
return key;
}
getKey(12).then((result) => { console.log(result) })
console.log('hello');
... to no avail! Which was inspired by:
How to use await with promisify for crypto.randomBytes?
Can anyone help me with this?
All I'm trying to do is to get randomBytes async. using the async./await block but ensure that it fulfills the promise before I carry on in the code.
This is an extension of my comment on the question
Since you're not promisify'ing or passing a callback to crypto.randomBytes() it is synchronous so you can't await it. Additionally, you're not properly awaiting the promise returned by g() at the top level. That is why you always see the pending Promise in your console.log()
You can use util.promisify() to convert crypto.randomBytes() into a promise returning function and await that. There is no need for the async/await in your example because all that is doing is wrapping a promise with a promise.
const { promisify } = require('util')
const randomBytesAsync = promisify(require('crypto').randomBytes)
function getKey (size) {
return randomBytesAsync(size)
}
// This will print the Buffer returned from crypto.randomBytes()
getKey(16)
.then(key => console.log(key))
If you want to use getKey() within an async/await style function it would be used like so
async function doSomethingWithKey () {
let result
const key = await getKey(16)
// do something with key
return result
}
If the callback function is not provided, the random bytes are generated synchronously and returned as a Buffer
// Synchronous
const {
randomBytes
} = await import('node:crypto');
const buf = randomBytes(256);
console.log(
`${buf.length} bytes of random data: ${buf.toString('hex')}`);
const crypto = require('crypto');
async function getKey(byteSize) {
const buffer = await new Promise((resolve, reject) => {
crypto.randomBytes(byteSize, function(ex, buffer) {
if (ex) {
reject("error generating token");
}
resolve(buffer);
});
}
async function g() {
let key = await getKey(12);
return key;
}
const crypto = require("crypto");
async function getRandomBytes(byteSize) {
return await new Promise((resolve, reject) => {
crypto.randomBytes(byteSize, (err, buffer) => {
if (err) {
reject(-1);
}
resolve(buffer);
});
});
}
async function doSomethingWithRandomBytes(byteSize) {
if (!byteSize) return -1;
const key = await getRandomBytes(byteSize);
//do something with key
}
doSomethingWithRandomBytes(16);

How can I use await fetch() in a promis so that it doesn't violate the eslint rule no-async-promise-executor?

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;
}
};

I get Promise { <pending> } as returned value and also calling in async scope gives me undefined immediately

Im trying to return a value from a Promise in async-await form and use it in another function in another file, but I do have problem because my Promise doesnt return any value.
When im trying to console.log('website') it returns me undefined immediately (it's like the value is not being fetched at all from API services). I dont know what im doing wrong, I really love to learn about Promises and Async-Await but each time im trying to work with them im getting more confused.
const dns = require('dns')
const iplocation = require("iplocation").default;
const emojiFlags = require('emoji-flags');
const getServerIPAddress = async (server) => {
return new Promise((resolve, reject) => {
dns.lookup(server, (err, address) => {
if (err) throw reject(err);
resolve(address);
});
});
};
const getServerLocation = async (server) => {
const ip = await getServerIPAddress(server)
iplocation(ip).then((res) => {
const country = emojiFlags.countryCode(res.countryCode)
const result = `Location: ${country.emoji} ${country.name}`
return result
})
.catch(err => {
return `Location: Unknown`
});
}
(async function() {
console.log(await getServerLocation('www.google.com'))
})()
module.exports = {
getServerLocation
}
It is really important for me to get result from this function first, then use its value in another function. I wish you could give me tips on how to do tasks asynchronously.
You're clearly using async so it's not apparent why you're using then as well. If you use then then you must return the promise as well in order to preserve the promise chain:
const getServerLocation = async (server) => {
const ip = await getServerIPAddress(server)
return iplocation(ip).then((res) => {
const country = emojiFlags.countryCode(res.countryCode)
const result = `Location: ${country.emoji} ${country.name}`
return result
})
.catch(err => {
return `Location: Unknown`
});
}
Otherwise just async this:
const getServerLocation = async (server) => {
const ip = await getServerIPAddress(server)
let res = await iplocation(ip);
const country = emojiFlags.countryCode(res.countryCode)
const result = `Location: ${country.emoji} ${country.name}`
return result
}
const getServerLocation = async (server) => {
const ip = await getServerIPAddress(server)
//you need to return
return iplocation(ip).then((res) => {
const country = emojiFlags.countryCode(res.countryCode)
const result = `Location: ${country.emoji} ${country.name}`
return result
})
.catch(err => {
return `Location: Unknown`
});
}

Using await in then callback - the keyword 'await' is reserved

In node.js, I have a database transaction, where I want to call an async method in then callback, but I get error message the keyword 'await' is reserved.
This is async saveImage function:
const saveImage = async (parsedLink) => {
AWS.config.region = config.awsSettings.region;
AWS.config.accessKeyId = config.awsSettings.accessKeyId;
AWS.config.secretAccessKey = config.awsSettings.secretAccessKey;
const bucket = new AWS.S3({
params: {
Bucket: config.awsSettings.images_bucket_name,
},
});
const currentDateString = new Date().toISOString().replace(/\:|\./g, '-');
const bodystream = new Buffer(parsedLink.imgUrl, 'binary');
const imageUrlDomain = parseDomain(parsedLink.linkUrl).domain;
const params = {
Key: `${parsedLink.id}/${imageUrlDomain}_${currentDateString}${parsedLink.imgType}`,
ContentType: parsedLink.imageMime,
ContentEncoding: 'base64',
Body: bodystream,
};
const resultPromise = await bucket.upload(params).promise();
return resultPromise.Location;
};
If I want to use saveImage function, I get the error message.
module.exports.addTestObject = async (ctx) => {
const testObj = ctx.request.body;
try {
switch (testObj.type) {
case interestT.getType.link: {
const knexTestObject = TestObject.knex();
transaction(knexTestObject, trx =>
TestObject.query(trx)
.insert({
interestDate: testObj.date,
})
.then(newInterest => {
// save image
if (parsedLink.saveImg) {
parsedLink.imgUrl = await saveImage(testObj);
}
newInterest.$relatedQuery('linkInterestsRel', trx).insert({
linkHeader: testObj.linkHeader,
}),
}
),
)
.then((linkInterest) => {
console.log(linkInterest);
})
.catch((err) => {
throw err;
});
break;
}
default:
break;
}
ctx.response.body = interestObj;
} catch (err) {
const statusCode = err.status || 400;
ctx.throw(statusCode, err.message);
}
};
Regular functions run synchronously till they return. Therefore you cannot use await inside them as you cannot wait for an asynchronous event in a synchronous way.
JavaScript also has async functions, which look like regular functions, but are conceptually quite different: They run synchronously till they reach an await, then they stop and continue once the awaited Promise resolves. As such they cannot return their result synchronously, instead they return a Promise which then resolves when the function finished execution.
Therefore you need to convert your function into an async function:
async function getUsername() { // <-- async keyword here
return (await getUser()).name; // <-- await can be used inside
}
Now this does also work inside a .then callback:
getUser().then(async function(user) {
const friends = await getFriends(user);
// ...
})
But this somewhat mixes the abstraction async functions with their underlying primitive Promise. If you would just await the Promise instead of adding a .then callback, the code gets way more readable:
(async function() {
const user = await getUser();
const friends = await getFriends(user);
})();
The concrete question could be rewritten as:
const linkInterest = await transaction(knexTestObject, async trx => {
const newInterest = await TestObject.query(trx)
.insert({ interestDate: testObj.date, });
if (parsedLink.saveImg) {
parsedLink.imgUrl = await saveImage(testObj);
}
await newInterest.$relatedQuery('linkInterestsRel', trx)
.insert({ linkHeader: testObj.linkHeader, }),
});

Categories