Why the output shows "Promise { }" when it expected to shows "Bienvenue"
const translate = require('google-translate-api');
async function translateSentence(sentence, languebase, languagetranslation) {
var sentenceTranslated = await translate(
sentence,
{ from: languebase, to: languagetranslation });
return sentenceTranslated.text;
}
var Translatedtext = translateSentence("Welcome", "en", "fr");
console.log(Translatedtext);
UPDATE:
I'm trying to return the translated data into JSON here is what I'm trying to do:
data = new Object();
data.Translatedtext = Translatedtext;
var string = JSON.stringify(data);
console.log(JSON.parse(string));
The out shows as { Translatedtext: {} } and I expected something like { Translatedtext: {Bienvenue} }
Because async functions return promises, so Translatedtext is a reference to a promise, and when you dump it out, you see the details of that promise, including the fact that it's pending.
If you meant to get the result, you'd have to await it (or use then):
var Translatedtext = await translateSentence("Welcome", "en", "fr");
// ------------------^
console.log(Translatedtext);
(handling the exception if it rejects), or
translateSentence("Welcome", "en", "fr")
.then(Translatedtext => {
console.log(Translatedtext);
})
.catch(err => {
// Handle the fact an error occurred
});
Note that to use await, you'd have to be in an async function.
If your code is written with async/await it does not mean that you can get the value in not an async function. Your function just returns the Promise. Anyway you need to write like
translateSentence("Welcome", "en", "fr").then(text => console.log(text));
or call this function in the another async function
async anotherFunction() {
const text = await translateSentence("Welcome", "en", "fr");
console.log(text);
}
Assuming translate is returning a promise, we could make an async function and wait for translateSentence to do it's thing then add the text to the object.
This would be done like this:
async function performOperations(){
let Translatedtext = await translateSentence("Welcome", "en", "fr")
data = new Object();
data.Translatedtext = Translatedtext;
var string = JSON.stringify(data);
console.log(JSON.parse(string));
}
performOperations()
What you are doing is checking the object before it has finished processing the request to the google api. So your data is more than likely getting to its location, its just that you're looking at the object too soon.
translateSentence is defined as async, thus it returns a Promise.
This means you need to wait for the promise resolve/reject before being able to access the result:
translateSentence("Welcome", "en", "fr")
.then(Translatedtext => {
var data = { Translatedtext };
var string = JSON.stringify(data);
console.log(JSON.parse(string));
})
.catch(err => console.log(err);
Related
So basically, I am using fetch to get the data from my database. I wrote a few JS functions that will take effect once the user clicks on the like button. One of those functions will post the new data to the server (that is what it is intended to do later on but for now, I am just printing the output). The output from that function is a promise object that is being returned to the server in the form of a json object. How can I get my desired output which is the VALUE of that promise?
The JavaScript code:
<script>
const likebtn = document.getElementById('likebtn');
const currentURL = window.location.href;
const likenum = document.getElementById('likenumber');
const postarray = currentURL.split("/");
const postName = postarray[4];
// console.log(postName)
function setLikeBtnColor() {
likebtn.style.color = JSON.parse(localStorage.getItem('likebtn')) ? 'cornflowerblue':'black';
}
setLikeBtnColor();
async function getlikenumber() {
const response1 = await fetch('/postlikes/'+postName)
fetchData = await response1.json()
likenum.textContent = fetchData.post_likes
return fetchData
}
async function getLikeNumber() {
const response = await fetch('/postlikes/'+postName)
fetchData = await response.json()
likenum.textContent = fetchData.post_likes
return fetchData
}
function myFunction() {
localStorage.setItem('likebtn', !JSON.parse(localStorage.getItem('likebtn')));
setLikeBtnColor();
if (likebtn.style.color === 'cornflowerblue') {
let currentLikeNum = getLikeNumber()
fetch('/postlikes/'+postName, {
method:"POST",
body: JSON.stringify({
post_likes:currentLikeNum+1
}),
headers:{
"Content-type":"application/json; charset=UTF-8"
}
})
getlikenumber()
} else {
let currentLikeNum = getLikeNumber();
fetch('/postlikes/'+postName, {
method:"POST",
body: JSON.stringify({
post_likes:currentLikeNum
}),
headers:{
"Content-type":"application/json; charset=UTF-8"
}
})
getlikenumber()
}};
likebtn.addEventListener('click', myFunction);
getlikenumber()
</script>
The python/flask code:
#app.route('/postlikes/<string:post_name>', methods=["GET","POST"])
def postlikes(post_name):
if request.method == "GET":
post = Image.query.filter_by(post_name=post_name).first()
# return "{'post likes':" + "'" + str(post.likes) + "'}"
return {"post_likes":post.likes}
else:
print(request.json)
My desired output:
{'post_likes':1}
or
{'post_likes':'1'}
the output I am getting:
{'post_likes': '[object Promise]1'}
P.S the initial value of the likes on the post_likes is 0.
getLikeNumber() returns a promise because an async function always returns a promise.
The keyword async just makes your whole function one big promise that await other promises inside its body, crudely abstracted.
So when you write :
let currentLikeNum = getLikeNumber() // currentLikeNum is a promise return
fetch('/postlikes/'+postName, {
method:"POST",
body: JSON.stringify({
post_likes:currentLikeNum+1 // currentLikeNum is a promise return converted to a string + "1"
So what you want is to either keep your function myFunction async and await your promise to keeps only the returns, like you already did with getLikeNumber()
Or with the old way :
getLikeNumber().then( res => {
//do your post here with the res variable
})
But that would not be consistent with your previous function.
In any case I would suggest to read one tutorial on async/await VS .then/.catch to continue your project comfortably.
Have a nice day !
I am trying to execute the following code, however "// go do something else" keeps happening before "// do stuff with things"
It appears that my code is not waiting for mongoose.model('things').find() to finish before moving on. I've tried different variations of async/await and nothing seems to work.
Not getting errors an everything executes, just out of order.
const asyncFunction = async () => {
mongoose.connect(`mongodb+srv://...`);
mongoose.model('things', {data:String});
mongoose.model('things').find((err, things)=>{
// do stuff with things
}
console.log('something');
}
const otherAsyncFunction = async () {
await asyncFunction();
// go do something else
}
otherAsyncFunction();
Your asyncFunction doesn't return anything, so there's no point awaiting it.
You have no Mongoose schema.
The syntax to create a Mongoose model (doc) is :
const thingsShema = new mongoose.Schema({ data: 'string' });
const Thing = mongoose.model('thing', thingsShema );
You are creating your model, but then your model isn't stored in a variable and you're not using it at all.
mongoose.model('things') : this line creates a new Mongoose model but you're not passing it any schema. Anyway you already did that on the previous line.
.find() is asynchronous, and you're not returning its value.
You aren't passing any argument to .find(), only a callback function.
This code should work better :
const asyncFunction = async () => {
await mongoose.connect(`mongodb+srv://...`);
const thingsSchema = new mongoose.Schema({ data: 'string' });
const Things = mongoose.model('things', thingsSchema);
const foundThings = await Things
.find({}) // Query conditions (here, querying for 'everything', an empty object)
.lean() // Returns simple JSON and not a collection of Mongoose objects
.exec(); // returns a true Promise and not just a thenable
console.log('foundThings = ', foundThings);
return foundThings; // this returns a Promise, because 'async' functions always do
}
const otherAsyncFunction = async () => {
const result = await asyncFunction();
console.log("Result = ", result); // Normally this will log the same thing as 'foundThings'
// go do something else
}
otherAsyncFunction();
async functions return Promise object. When you exec await asyncFunction(), 'await' wait status asyncFunction() - resolve or reject.But in your code there are no resolve() or reject() functions. So you need to do like this:
const asyncFunction = async (resolve) => {
mongoose.connect(`mongodb+srv://...`);
mongoose.model('things', {data:String});
mongoose.model('things').find((err, things)=>{
// do stuff with things
});
console.log('something');
resolve()
}
const otherAsyncFunction = async () => {
await asyncFunction();
// go do something else
}
otherAsyncFunction();
I am using Javascipt AWS-SDK to scan AWS dynamodb. I expect my code to hold execution until it gets the result from the scan. What did I do wrong .
async function scanDb() {
var docClient = new AWS.DynamoDB.DocumentClient();
params = {
TableName: 'testdriveenvs',
FilterExpression : 'EnvStatus = :a',
ExpressionAttributeValues : {':a' : 'Inuse'}
};
var objectPromise = await docClient.scan(params).promise().then((data) => {
return data.Items
});
return objectPromise;
}
var resultDb = scanDb();
console.log ("Result",resultDb);
Expected output : Scan results from DynamoDB.
Actual Output : Promise { "pending" }
: "pending"
: PromiseProto { … }
scanDb is an async function, so it will necessarily return a promise. All async functions return promises. Either call .then on that promise, or use it in an async function and await its result.
scanDb()
.then(resultDb => {
console.log(resultDb);
});
async function someFunction() {
const resultDb = await scanDb();
console.log(resultDb);
}
Await works on only inside async function, so it will hold the code after await, which is inside async. I was trying to get the value of scanDb() function outside of async.That the reason my code was not waiting.
Thanks a lot to Nicholas.
I'm quite a newbie in JavaScript and in Promises.
I'm trying to build an array of objects that I get from an API.
To do so, I've build two functions in a file MyFile.js.
The first one returns a promise when an axios promise is resolved. It's
function get_items (url) {
return new Promise((resolve, reject) => {
let options = {
baseURL: url,
method: 'get'
}
axios(options)
.then(response => {
resolve(response.data)
})
.catch(error => {
reject(error.stack)
})
})
}
The second one looks like this:
let output = []
let next_url = 'https://some_url.com/api/data'
async function get_data () {
try {
let promise = new Promise((resolve, reject) => {
if (next_url) {
get_items(next_url)
.then(response => {
output.push(...response.results)
if (response.next) {
next_url = response.next
console.log('NEXT_URL HERE', next_url)
get_data()
} else {
console.log('else')
next_url = false
get_data()
}
})
.catch(error => {
reject(error.stack)
})
} else {
console.log('before resolve')
resolve(output)
}
})
return await promise
} catch(e) {
console.log(e)
}
}
It's where I'm grinding my teeth.
What I think I understand of this function, is that:
it's returning the value of a promise (that's what I understand return await promise is doing)
it's a recursive function. So, if there is a next_url, the function continues on. But if there is not, it gets called one last time to go into the else part where it resolves the array output which contains the results (values not state) of all the promises. At least, when I execute it, and check for my sanity checks with the console.log I wrote, it works.
So, output is filled with data and that's great.
But, when I call this function from another file MyOtherFile.js, like this:
final_output = []
MyFile.get_data()
.then(result => {
console.log('getting data')
final_output.push(...result)
})
it never gets into the then part. And when I console.log MyFile.get_data(), it's a pending promise.
So, what I would like to do, is be able to make get_data() wait for all the promises result (without using Promise.all(), to have calls in serie, not in parallel, that would be great for performances, I guess?) and then be able to retrieve that response in the then part when calling this function from anywhere else.
Keep in mind that I'm really a newbie in promises and JavaScript in general (I'm more of a Python guy).
Let me know if my question isn't clear enough.
I've been scratching my head for two days now and it feels like I'm running in circle.
Thanks for being an awesome community!
This is a bit untested
const api_url = 'https://some_url.com/api/data';
get_data(api_url).then((results) => {
console.log(results);
}).catch((error) => {
// console.error(error);
});
function get_items (url) {
const options = {
baseURL: url,
method: 'get'
};
return axios(options).then((response) => response.data);
}
async function get_data(next_url) {
const output = [];
while (next_url) {
const { results, next } = await get_items(next_url);
output.push(...results);
next_url = next;
}
return output;
}
Basically it makes things a bit neater. I suggest to look at more examples with Promises and the advantage and when to ease await/async. One thing to keep in mind, if you return a Promise, it will follow the entire then chain, and it will always return a Promise with a value of the last then.. if that makes sense :)
There are a few problems. One is that you never resolve the initial Promise unless the else block is entered. Another is that you should return the recursive get_data call every time, so that it can be properly chained with the initial Promise. You may also consider avoiding the explicit promise construction antipattern - get_items already returns a Promise, so there's no need to construct another one (same for the inside of get_items, axios calls return Promises too).
You might consider a plain while loop, reassigning the next_url string until it's falsey:
function get_items (baseURL) {
const options = {
baseURL: url,
method: 'get'
}
// return the axios call, handle errors in the consumer instead:
return axios(options)
.then(res => res.data)
}
async function get_data() {
const output = []
let next_url = 'https://some_url.com/api/data'
try {
while (next_url) {
const response = await get_items(next_url);
output.push(...response.results)
next_url = response.next;
}
} catch (e) {
// handle errors *here*, perhaps
console.log(e)
}
return output;
}
Note that .catch will result in a Promise being converted from a rejected Promise to a resolved one - you don't want to .catch everywhere, because that will make it difficult for the caller to detect errors.
Another way of doing it is to not use async at all and just recursively return a promise:
const getItems = (url) =>
axios({
baseURL: url,
method: 'get',
}).then((response) => response.data);
const getData = (initialUrl) => {
const recur = (result, nextUrl) =>
!nextUrl
? Promise.resolve(result)
: getItems(nextUrl).then((data) =>
recur(result.concat([data.results]), data.next),
);
return recur([],initialUrl)
.catch(e=>Promise.reject(e.stack));//reject with error stack
};
As CertainPerformance noted; you don't need to catch at every level, if you want getData to reject with error.stack you only need to catch it once.
However; if you had 100 next urls and 99 of them were fine but only the last one failed would you like to reject in a way that keeps the results so far so you can try again?
If you do then the code could look something like this:
const getData = (initialUrl) => {
const recur = (result, nextUrl) =>
!nextUrl
? Promise.resolve(result)
: getItems(nextUrl)
.catch(e=>Promise.reject([e,result]))//reject with error and result so far
.then((data) =>
recur(result.concat([data.results]), data.next),
);
return recur([],initialUrl);//do not catch here, just let it reject with error and result
};
I've been reading up on promises for a few hours and I'm loosing my mind here. According to what I've read in SO and articles on google. To get the value of a response in a variable I have to use async and await. So going that route I've written this code:
async function getZpid() {
let response = await function getZillowZpid(){
zillow.get('GetSearchResults', parameters)
.then(results => {
let zpidResponse = results.response.results.result[0].zpid;
console.log("i ran");
return zpidResponse;
});
}
}
getZpid();
Here I would expect that when getZpid() runs "response" would wait for the function get ZillowZpid to be done. Once it would be completed it would console.log "i ran" and then return the zpidResponse.
I get no error but the console.log never appears. Ultimately the console.log is just a test what I am trying to do is get zpidResponse in to a variable I could use outside the function. Any help would be greatly appreciated!
You are defining an extraneous function with await function getZillowZpid() which you never call. This is why you see no error or results. If you log the variable response in your function above you will see that it is something [Function: getZillowZpid], you've defined a function and assigned it to response which is certainly not what you want.
Since zillow.get returns a promise, you can just await that. Here's an example with a mocked zillow object:
// fake the zillow object
let zillow = {
get() {
return Promise.resolve({response: {results: {result: [{zpid: "Some data"}]}}})
}
}
async function getZpid() {
let parameters = {}
// zillow.get returns a promise, you can use await to get the returned value
let response = await zillow.get('GetSearchResults', parameters)
.then(results => {
let zpidResponse = results.response.results.result[0].zpid;
console.log("i ran");
return zpidResponse;
});
console.log(response)
}
getZpid();
FYI, if you're using async/await it's cleaner to avoid the then() although you still should add some error-checking:
// fake zillow
let zillow = {
get() {
return Promise.resolve({response: {results: {result: [{zpid: "Some data"}]}}})
}
}
async function getZpid() {
let parameters = 0
let response = await zillow.get('GetSearchResults', parameters)
let zpidResponse = response.response.results.result[0].zpid;
console.log(zpidResponse)
return zpidResponse
}
getZpid();