I am trying to set a global variable within a function, but the code continues before the variable has been updated.
e.g.
var username = 'Example';
const fetch = require('node-fetch');
var num = 1234;
var uuidP;
const request = async () => {
const response = await fetch(`https://api.mojang.com/users/profiles/minecraft/${username}`);
const json = await response.json();
uuidP = json.id;
}
request();
console.log(num); //returns 1234
console.log(uuidP); //returns udefined
Javascript is heavily optimised. You need to declare the update() function is asynchronous, and then use a Promise to await the response of the update. Have a look at this example.
Related
I am fairly new to Javascript and I understand that it executes asynchronously. I tried using the callback method to fetch the secret values and then execute next block of code. But it is not waiting.
This is the function that fetches the keyvault secret values
function getsecret_values(client,secret_name,callback) {
let val = []
for (let i =0;i<secret_name.length;i++){
client.getSecret(secret_name[i]).then((latestSecret) => {
val[i] = latestSecret.value;
})
}
callback(val)
}
I am calling getsecret_values function from main block
let vaultName = result.database;
const url = `https://${vaultName}.vault.azure.net`;
const credential = new ClientSecretCredential(result.host, result.user, result.password);
const client = new SecretClient(url, credential);
let secret_values = []
getsecret_values(client, secrets, function(result) {
secret_values = result
console.log(secret_values)
});
console.log(secret_values)
\\next code block
Both the console.log returns empty array.
I want my code to wait till the secret values are fetched and put into secret_values array and then proceed to next block of code. How do I achieve this?
the easiest way is to use Async Await pattern, which uses promises in the background. Trying not to change your code much:
async function getsecret_values(client,secret_name) {
let val = []
for (let i =0;i<secret_name.length;i++){
const latestSecret = await client.getSecret(secret_name[i])
val[i] = latestSecret.value;
}
return val
}
in your main block:
getsecret_values(client, secrets).then(function(result) {
secret_values = result
console.log(secret_values)
});
console.log(secret_values) // will still be an empty array as the then function has not been executed yet....
my approach would be:
async function getsecret_values(client,secret_name) {
let val = []
for (let i =0;i<secret_name.length;i++){
const latestSecret = await client.getSecret(secret_name[i])
val[i] = latestSecret.value;
}
return val
}
// main:
async function main() {
let vaultName = result.database;
const url = `https://${vaultName}.vault.azure.net`;
const credential = new ClientSecretCredential(result.host, result.user, result.password);
const client = new SecretClient(url, credential);
const secret_values = await getsecret_values(client, secrets)
console.log(secret_values)
}
main()
first off I'd like to make clear that I'm new to node.js and this may sound like a silly question but, how am I supposed to return data out of model.find() function in mongoose ( eg. with a var.exports = var )?<
const data = () =>
{
MyModel.find().then(function(result){
console.log(result);
return(result);
});
}
exports.data = data
Being the query asyncronous I'm not able to retrieve these data until the function is completed (so never). Is there anyway to return these informations in a variable eg:
const retriever = require('../utils/test.js') //calling the exports file
test = retriever.data
console.log(test)
Thank you very much in advance
With promises you can achieve it as follows
const data = () => {
return MyModel.find({});
}
// using it in another function
const result = await data();
1.You can use a callback, as below
const data = (callback) =>
{
MyModel.find().then(function(result){
console.log(result);
//return(result);
callback(results);//we pass in a function which will be used to pull out
//data
});
}
exports.data = data
// THE AREA WHERE THIS CODE IS USED
const {data} = require('./to/data')
//show data
data(function (result) {
console.log( result );// data from callback
})
2. using async/await promies
const data = async () =>
{
let results = await MyModel.find();
}
exports.data = data
ON USING THIS FUNCTION
const {data} = require('./to/data')
(async function () {
let res = await data();
console.log(res);
})()
My javascript code..
function testdata(){
var strtest_data='';
var strtest1_data='';
d3.json("js/test.json").then(function(test_json) {
strtest_data=JSON.stringify(test_json);
console.log(strtest_data);
})
d3.json("js/test.json").then(function(test_json1) {
strtest1_data=JSON.stringify(test_json1);
console.log(strtest_data1);
})
console.log(strtest_data);
var testobj=JSON.parse(strtest_data);
var testobj1=JSON.parse(strtest_data1);
console.log(JSON.stringify({data:testobj.quiz, more:testobj1.maths}));
}
In the above code I'm calling two functions using d3.json (for brevity in this question I'm calling for the same test.json) and then with the results calling another function. Here the function is console.log but in actual scenario could be a ajax POST call using fetch.
The above code does not work as the bottom part of the code gets run prior to d3.json getting finished..
I would sincerely appreciate any help in solving this.
Thanks
d3.json is asynchronous method, so if you want to call it sequentially, use async/await
async function testdata() {
let strtest_data = ""
let strtest1_data = ""
const test_json = await d3.json("js/test.json")
strtest_data = JSON.stringify(test_json)
console.log(strtest_data)
const test_json1 = await d3.json("js/test.json")
strtest1_data = JSON.stringify(test_json1)
console.log(strtest_data1)
var testobj = JSON.parse(strtest_data)
var testobj1 = JSON.parse(strtest_data1)
console.log(JSON.stringify({ data: testobj.quiz, more: testobj1.maths }))
}
or call it concurently using Promise.all
async function testdata() {
let strtest_data = ""
let strtest1_data = ""
const [test_json, test_json1] = await Promise.all([
d3.json("js/test.json"),
d3.json("js/test.json"),
])
strtest_data = JSON.stringify(test_json)
strtest1_data = JSON.stringify(test_json1)
console.log(strtest_data)
console.log(strtest_data1)
var testobj = JSON.parse(strtest_data)
var testobj1 = JSON.parse(strtest_data1)
console.log(JSON.stringify({ data: testobj.quiz, more: testobj1.maths }))
}
Here I think
Promise.all([ d3.json("js/test.json")
d3.json("js/test.json")].then(data =>{
//call your other function and access using data array and make your call
}).catch(e=>console.error("error ",e));
This function is going to execute both calls when they finish then it will put the result in data array. If any error comes in either of the call you will have it in the catch block. You can do whatever you want to in the then block if all calls are completed successfully.
I am trying to access return data from a do while loop, but I am unable to do so.
I have stored the information in a new variable (starships) and then returned this variable, but it says starships is not defined. I see that this may be a scoping issue, how can I resolve this?
async function getData() {
const allResults = [];
let url = 'https://swapi.co/api/starships/';
do {
const res = await fetch(url);
const data = await res.json();
url = data.next;
allResults.push(...data.results);
console.log(allResults);
} while (url !== null)
let starships = allResults;
return starships;
}
console.log(starships);
You need to get the value which is returned from getData. The most obvious way to do this with the async/await structure you have is to just await it:
async function getData() {
const allResults = [];
let url = 'https://swapi.co/api/starships/';
do {
const res = await fetch(url);
const data = await res.json();
url = data.next;
allResults.push(...data.results);
console.log(allResults);
} while (url !== null)
let starships = allResults;
return starships;
}
async function doTheDo() {
const test = await getData();
console.dir(test);
}
doTheDo();
you can do this. starships is defined inside the loop. Additionally, you are not calling getData() function. You can store that return value like this
const result = await getData();
console.log(result);
or you can directly print like this. console.log(await getData())
async function getData() {
const allResults = [];
let url = 'https://swapi.co/api/starships/';
do {
const res = await fetch(url);
const data = await res.json();
url = data.next;
allResults.push(...data.results);
console.log(allResults);
} while (url !== null)
return allResults;
}
console.log(await getData());
Async functions return a promise, which means you have to access the return value with a .then().
However, you have another problem: starships is in the scope of the function getData() which you have defined, but not called.
So first lets call your function:
async function getData() {
const allResults = [];
// do stuff
let starships = allResults;
return starships;
}
console.log(getData());
Now you will see that your log value is [object Promise] which isn't so helpful in its current form. This is because the code outside the async function is running synchronously, which means we don't have the value yet, just a promise to maybe return the value sometime in the future.
So now we need to access the promise asynchronously using the .then() like so:
async function getData() {
const allResults = [];
// do stuff
let starships = allResults;
return starships;
}
getData().then(starships => {
console.log(starships);
});
Now you should see the info you were expecting to be logged.
You can also save promise to a variable and pass it around and access it elsewhere in your code like so:
async function getData() {
const allResults = [];
// do stuff
let starships = allResults;
return starships;
}
let starshipPromise = getData();
// time & code passes...
starshipPromise.then(starship => {
console.log(starship);
}).catch(error => {
// handle error
});
And don't forget to catch your rejected promises!
See the MDN docs on Async functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
And if you need more info on promises, go here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
var accountA;
var accountB;
accounts = async () => {
accountA = await server.loadAccount(Apub)
console.log(accountA)
accountB = await (server.loadAccount(Bpub))
}
accounts()
console.log(accountA);
1) Apub is my public key which i have already declared
2)when i am printing the
accountA
inside the function it is showing me complete details from accountA
3) when i do console.log outside the function, the output is
undefined
4) i have declared the variables outside the function as the global scope
please help me
Although you are using await inside the function you are not waiting till it you get a response while you call accounts which is an async function
var accountA;
var accountB;
accounts = async () => {
accountA = await server.loadAccount(Apub)
console.log(accountA)
accountB = await (server.loadAccount(Bpub))
}
accounts().then(() => {
console.log(accountA);
})
If you have the above code in a function which is async then you could use await with accounts too
await accounts()
Your accounts function is asyncronous. So the console.log() in the last line is called first, before accounts has time to finish. This is why it displays undefined. You have to wait for accounts to finish before printing it by adding an "await" before your call.
var accountA;
var accountB;
accounts = async () => {
accountA = await server.loadAccount(Apub)
console.log(accountA)
accountB = await (server.loadAccount(Bpub))
}
await accounts()
console.log(accountA);