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 trying to push in an array all the ids of objects that match my condition.
I am using a recursive function and I want to return a value when my recursive function has finished.
Here is my code :
const getFamilies = async function (family, famillesReliees) {
await strapi.query('famille-de-materiel').findOne({ id: family })
.then(res => {
if (res.cats_enfant.length > 0) {
res.cats_enfant.forEach(async enfant => {
famillesReliees = await getFamilies(enfant.id, famillesReliees)
})
} else {
famillesReliees.push(res.id)
}
})
return famillesReliees
}
async search() {
let value = await getFamilies(2, [])
return value
}
I don't understand why the "value" return before the end of the recursive function
This isn't doing what you think:
getFamilies(2).then(console.log('getFamilies then'))
This executes console.log immediately and passes its result (which is undefined) as the function to be executed after the getFamilies operation.
Wrap the console.log operation in a function to be executed later:
getFamilies(2).then(() => console.log('getFamilies then'))
Structurally, this is just like your use of .then() in the getFamilies function above. The only differences are:
There are no parameters/arguments for the function, so just use () instead of a variable name. (Your callback function above has a parameter called res.)
There's only one line in the function, so the curly braces {} aren't needed. (Technically this also returns the result of that line, but in this case the returned result is undefined and nothing uses it so no harm done.)
Related
This question already has answers here:
Is the Promise constructor callback executed asynchronously?
(2 answers)
When is the body of a Promise executed?
(4 answers)
Closed 2 months ago.
I read about event loop and callback queue and micro/macro task queue but maybe i am getting something the wrong way,
Can someone visualize it for me?, it will help me understand so mush concepts.
console.log(1)
const wait2sec = new Promise((resolve, reject) => {
console.log(2)
setTimeout(() => {
console.log(3)
resolve(true)
}, 2000)
console.log(4)
})
const X =async () => {
await wait2sec
console.log('ok')
}
X()
console.log(5)
I think it should log: 1,5,2,4,3,ok
but it logs: 1,2,4,5,3,ok
From MDN (emphasis mine):
The body of an async function can be thought of as being split by zero or more await expressions. Top-level code, up to and including the first await expression (if there is one), is run synchronously. In this way, an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously.
This is what happens here, the code of X and of wait2sec is run synchronously, hence before the console.log(5).
You expected concurrent behavior between Promise object and console.log and don't saw it?
You created and immediately called the Promise object (so you can't see 5 before 2,4, at least declare wait2sec as a function).
Promise object without await or timeout runs as a synchronous function (so you see 2,4 and after 3)
if you want to see concurrency between two processes see such code:
function RandomWork(prefix) {
return new Promise( resolve => {
let time = Math.round(Math.random() * 10);
setTimeout(function() {
console.log(prefix, 'made some work for:', time, 'ms')
resolve('foo');
}, time);
});
}
const Process = async(name) => {
const prefix = "process_"+name;
console.log(prefix, 'start');
for(let i=1; i<10; i++) {
await RandomWork(prefix);
}
console.log(prefix, 'stop');
}
Process(1);
Process(2);
This question already has answers here:
How can I access the value of a promise?
(14 answers)
Why is my asynchronous function returning Promise { <pending> } instead of a value?
(9 answers)
Closed 1 year ago.
As parent function does not support async. I need to make call without await and get return value. As suggested on most of the posts, applied promise with then and returning value. But it prints as "promise" instead of return "value".
Can you please share, how to achieve return value instead of promise.
code sandbox:
https://codesandbox.io/s/await-without-async-and-return-value-qbs7t?file=/src/index.js
await isEnable(data) {
try {
...
return true;
}
catch (e) {
console.error(e);
}
}
}
const getEnableStatus=(data) =>{
return isEnable(data).then((result) =>
{console.log(result); return result;}); //this prints correctly but, need this in return result.
}
console.log(getEnableStatus(data)); //it always print 'promise'. how to get value here instead of promise.
Pass in a callback to the getEnableStatus function, and then call it with the returned data.
// Mock function that resolves after
// two seconds
function isEnable() {
return new Promise((res, rej) => {
setTimeout(() => res('Hallo!'), 2000);
});
}
// Accept a callback, and call it with the data
function getEnableStatus(data, callback) {
isEnable(data).then(callback);
}
// The callback logs the data
getEnableStatus('data', function (data) {
console.log(data);
});
This question already has answers here:
Using async/await with a forEach loop
(33 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I am trying to sort names in two different array. but when I need to return the final result, it will just return the values first then do the forEach.
const available = [];
const taken = [];
const names = data.split('\n');
names.forEach(async (name, i) => {
(data.success !== undefined) ? (availabe.push(name)) : (taken.push(name));
});
return { //This returns 0 for both
available: available.length,
taken: taken.length
}
The issue is that forEach doesn't wait for async code. Check here: https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404
Try this instead:
async function f() {
const available = [];
const taken = [];
const names = data.split('\n');
for (const name of names) {
// await request...
(data.success !== undefined) ? (availabe.push(name)) : (taken.push(name));
}
return { //This returns 0 for both
available: available.length,
taken: taken.length
}
}
Then, when you call f(), make sure you await f().
Side note: if you have very many names, this could get very slow. You're waiting for each request to complete before beginning the next one. You'll want to look into requesting all the data at once, either with a different http endpoint, or using something like Promise.all() or the async library.
The variable name "available" is misspelled as "availabe" in line 8. Other syntax errors may exist; you might try using something link jslint.com.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
So I am 99% sure this cannot be done, but humor me for a moment. Consider the two functions:
function doAjaxCall(fieldTocheckAgainst, currentField, value) {
axios.get(
window.location.origin +
'/api/clinic/'+window.id+'/patient/'+window.secondId+'/field-validation',
{
params: {
field_to_check_against: fieldTocheckAgainst,
current_field: currentField,
value: moment(value).format('YYYY-MM-DD')
}
}
).then((result) => {
return result.data
});
}
async function resolveAjaxCall(fieldTocheckAgainst, currentField, value) {
const result = await doAjaxCall(fieldTocheckAgainst, currentField, value)
console.log(result);
}
I am attempting to resolve the axios ajax call into a variable based on what I saw here and it doesn't work. I get undefined.
I understand when it comes to callbacks, everything has to be done in the callback, but is there no way, with async and await to resolve the promise to a variable as I am attempting to do, to then use said variable else where?
Or am I just going to be stuck with callbacks?
The only issue I see with your code is that axios.get() returns a Promise, but you aren't returning that promise from doAjaxCall. Promises are values, and they need to be passed around to be used.
Just add return before axios.get and that should give you the result you want.
--
On the question of "returning" from a promise - Async functions always return promises, even if you don't include a return statement. If your async function ends in the statement return true, it's actually returning a Promise that resolves to true. As you guessed in your original post, there is no way to pull a value out of a promise and into synchronous code.
You are missing the return statement in your doAjaxCall function, and you also need to treat the function as promise. It should be the following:
function doAjaxCall(fieldTocheckAgainst, currentField, value) {
return axios.get(
window.location.origin + '/api/clinic/'+window.id+'/patient/'+window.secondId+'/field-validation',
{
params: {
field_to_check_against: fieldTocheckAgainst,
current_field: currentField,
value: moment(value).format('YYYY-MM-DD')
}
}).then((result) => {
return result.data
});
}
async function resolveAjaxCall(fieldTocheckAgainst, currentField, value) {
const result = doAjaxCall(fieldTocheckAgainst, currentField, value).then(data = {
console.log(data);
})
}
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I'm new to JavaScript so sorry if the question is too dumb.
I have an async function getPartners() in file1.js wich returns an array like this:
return Promise.resolve(partners);
['1','2','3']
In file2.js I have an array with partnerIds and an emptyArray. My goal is when I call getPartners() in file2.js, emptyArray becomes equivalent to the function's return value. In other words I'd like to push the returned values to the emptyArray.
Currently I can get the values this way:
let emptyArray = listItems();
emptyArray.then((result) => {
console.log(result);
});
My problem is that if I try to console.log(emptyArray) outside of the .then, it's empty. I'd like to filter it too, after getting the values from the promise so I need to save the values into an array which I can call later in the code.
How can I do that?
EDIT:
This is what I want to achieve:
const { getPromiseResult } = require('./list');
let existingIds = ['1','2','3'];
let emptyArray = getPromiseResult();
emptyArray.then((resultArrayfromPromise) => {
console.log(resultArrayfromPromise) // ['2','3','4']
// filter the results by the existingIds array's elements
// get result: ['1','2','3','4']
// and get this result in a new filtered array which I can reach from the outside
});
filteredArray.dosomeotherstuff();
Since ES7, you can use async/await to get rid of then. await waits for operation to complete, and if there is a return value assigns it to the variable.
But you can only use the await in an async function so wrap your codes in it.
async function run() {
const { listItems } = require('./list');
let existingIds = ['1','2','3'];
let emptyArray = await getPromiseresult();
console.log(emptyArray); // now it's not empty
filteredArray.dosomeotherstuff();
}
run();