Access data outside an asynchronous call? - javascript

How can I access the vehicle data and assign it to data.diff after? I tried accessing the vehicle out the function but it's empty.
Code
schema.methods.log = function (data) {
let condition = { VIN: this.VIN }
let Vehicle = keystone.list('Vehicle');
async function myFunction() {
const vehicle = await Vehicle.model.findOne(condition)
if (vehicle) {
console.log("vehicle", vehicle)
}
}
//its empty
console.log("vehicle", vehicle)
data.diff = {
before: this,
after: vehicle,
}
myFunction()
return LogSchema.create(data)
}

How about this?
schema.methods.log = async function(data) {
let condition = { VIN: this.VIN }
let Vehicle = keystone.list('Vehicle');
const vehicle = await Vehicle.model.findOne(condition);
if (vehicle) {
console.log("vehicle", vehicle)
data.diff = {
before: this,
after: vehicle,
}
return LogSchema.create(data)
} else {
return "Some error message or object here...";
}
}

Related

return a value out of an eventListener that is inside of a forof loop

How can I pass the returned coin object from the displayCurrencies function to the getCoinId function to use it as a parameter in the API call for retrieving the specific coin data?
this is the function i created to return the value:
let returnID = (value) => {
return value;
};
this is the function that i want to return coin from:
let displayCurrencies = async () => {
let coinsContainer = document.querySelector(`.coins`);
try {
let coins = await getData();
let coinsArray = [];
let coinElement;
for (const coin of coins) {
coinElement = coin;
if (coinsArray.length > 20) {
break;
}
coinsArray.push(coin);
// create Nodes
let coinDisplay = createElement(`li`, `coin`);
let coinSymbolElement = createElement(`p`, `coinSymbol`);
let coinIDElement = createElement(`p`, `coinID`);
// set Values
coinSymbolElement.innerHTML = coin.symbol;
coinIDElement.innerHTML = coin.id;
// append
coinDisplay.append(coinSymbolElement, coinIDElement);
coinsContainer.appendChild(coinDisplay);
coinDisplay.addEventListener(`click`, () => {
openModal();
returnID(coin);
});
}
let returnCoin = returnID
coinDisplay.addEventListener(`click`, () => {
console.log(returnCoin);
});
console.log(returnCoin);
} catch (error) {
console.log(error);
}
};
and last, this is the function that i want to use the returned value at:
displayCurrencies();
let getCoinId = async () => {
let coinID = await displayCurrencies();
let currencyData = `https://api.coingecko.com/api/v3/coins/${coinID}`;
let responseData = await fetch(currencyData);
let dataOfCoins = await responseData.json();
console.log(dataOfCoins);
};
You can simply add an onclick event for each element, and when the call-back is called you invoke the getCoinID function passing the coinID as a parameter.
A simple example:
<ul class="coins">
</ul>
<script>
function addOnClick() {
let coinsContainer = document.querySelector('.coins');
let coins = [
{ id: 1, symbol: 'bitcoin' },
{ id: 3, symbol: 'brazil-fan-token' },
{ id: 4, symbol: 'celo-euro' },
]
for (const coin of coins) {
let coinDisplay = document.createElement('li')
let coinSymbolElement = document.createElement('p')
let coinIDElement = document.createElement('p')
coinSymbolElement.innerHTML = coin.symbol
coinIDElement.innerHTML = coin.id
coinDisplay.appendChild(coinIDElement)
coinDisplay.appendChild(coinSymbolElement)
coinsContainer.appendChild(coinDisplay)
coinDisplay.addEventListener('click', () => {
getCoinID(coin.symbol)
})
}
}
async function getCoinID(coinID) {
let currencyData = `https://api.coingecko.com/api/v3/coins/${coinID}`
let responseData = await fetch(currencyData)
let dataOfCoins = await responseData.json()
console.log(dataOfCoins)
}
addOnClick()
</script>

Nodejs Firestore: Returning nothing

I am using firebase to check a users punishment history, and when I call it:
I want it to return the array of embeds to post rather than just that. I am awaiting the function so I'm kind of confused why this is happening
This is what happens in the console.log:
[AsyncFunction: CheckHistory]
CALL
let hist = await CheckHistory(id);
console.log(CheckHistory);
FUNCTION
async function CheckHistory(user){
CheckBan(user);
let historyArray = [];
const colRef = db.collection('punishments')
colRef.where('user', '==', user).get().then(async querySnapshot => {
length = querySnapshot.size;
if (querySnapshot.empty){
console.log(querySnapshot.size)
return 0;
} else {
let docs = querySnapshot.docs;
for (let documentSnapshot of docs) {
const revoke = documentSnapshot.get('revoke')
let active = documentSnapshot.get('active')
if (active = true){
active = "Active"
} else {
active = `Revoked for ${revoke}`
}
const mod = documentSnapshot.get('mod')
const reason = documentSnapshot.get('reason');
const time = documentSnapshot.get('time');
let type = documentSnapshot.get('type');
if (type == 1){
type = "Blacklist";
} else if (type == 2){
type = "Dayban";
} else if (type == 3){
type = "Warning";
}
const username = await API.getUsernameFromId(user);
const modname = await API.getUsernameFromId(mod);
const historyEmbed = new MessageEmbed()
.setColor('#0099ff')
.setTitle(`'Punishment of ${username}:${user}`)
.setDescription(`This is a punishment log.`)
.addFields(
{ name: 'Status', value: `${active}`},
{ name: 'Moderator', value: `${modname}:${mod}` },
{ name: 'Reason', value: `${reason}` },
{ name: 'Type', value: `${type}` },
{ name: 'Time', value: `<t:${time}>`}
)
historyArray.push(historyEmbed);
if (historyArray.length >= length) {
return historyArray;
}
}
}
});
}
As stated by #Sergey Sosunov:
You forgot to actually return anything from your method, you should
return colRef.where('user', '==', user).get().then....
Or to change .then() callback approach to actually await one.
Like:
const querySnapshot = await colRef.where('user', '==', user).get();
and so on.
Also, the way you call the function only returns function definition; you should pass with parameters or print the variable value equal to your function. For example:
//Sample function
function test(id) { return id; }
//Returns function definition
console.log(test)
//Returns function value
console.log(test(1))
//Print variable value
let x = test(1)
console.log(x)

How to make recursive promise calls?

I am working with an API that gives me data with a limit per request (here 25). Therefore, I have to recursively make promises with fetch. However, while most of my logic works, when I try to return from the function it will return an empty array. The image below will make it more clear.
const url = (conf_name) => {
return (
"https://api.elsevier.com/content/search/scopus?view=COMPLETE&cursor=*&query=CONFNAME(" +
conf_name +
")%20AND%20DOCTYPE(cp)%20AND%20SRCTYPE(p)&field=dc:creator,dc:title,dc:description,affilname,affiliation-city,affiliation-country,authkeywords,prism:doi,prism:doi,prism:coverDate"
);
};
const savePapers = (json, conf_name) => {
let temp = new Array();
for (let i = 0; i < json["search-results"]["entry"].length; i++) {
temp[i] = {
title: json["search-results"]["entry"][i]["dc:title"],
author: json["search-results"]["entry"][i]["dc:creator"],
publication_date: json["search-results"]["entry"][i]["prism:coverDate"],
doi: json["search-results"]["entry"][i]["prism:doi"],
abstract: json["search-results"]["entry"][i]["dc:description"],
author_keywords: json["search-results"]["entry"][i]["authkeywords"],
proceeding: conf_name,
};
}
return temp;
};
async function getPapers(final, url, conf_name) {
let total_amount_of_papers;
let next;
let position = 2;
try {
let response = await fetch(url, options);
let json = await response.json();
total_amount_of_papers = json["search-results"]["opensearch:totalResults"];
if (json["search-results"]["link"][position]["#ref"] == "prev")
next = json["search-results"]["link"][position + 1]["#href"];
next = json["search-results"]["link"][position]["#href"];
final = final.concat(savePapers(json, conf_name));
if (final.length === 50) {
console.log("hey",final.length);
return final;
}
await getPapers(final, next, conf_name);
} catch (error) {
console.log(error);
}
}
const createNewConf = async (conferences) => {
let final = new Array();
try {
var temp = new Conference({
acronym: conferences.acronym,
name: conferences.fullname,
area: conferences.area,
subarea: conferences.subarea,
location: conferences.location,
url: conferences.url,
description: conferences.description,
papers: await getPapers(final, url(conferences.acronym),conferences.acronym),
});
console.log(temp.papers.length);
} catch (error) {
console.log(error);
}
return temp;
};
describe("Saving records", function () {
it("Saved records to the database", async function (done) {
var conferences = [];
try {
for (var i = 0; i <= 1; i++) {
conferences[i] = await createNewConf(json_conferences[i]);
conferences[i].save().then(function () {
assert(conferences[i].isNew === True);
done();
});
}
mongoose.connection.close();
} catch (error) {
console.log(error);
}
});
});
Below you can see the length of my final array after passing the if to stop fetching more. and the second number is what I receive in the initial call
Console
Maybe anyone has an idea of the undefined behavior that occurs during return.
Your help is much appreciated.

Use async API call inside loop in computed property with vue-async-computed

I have a computed property inside a Vue component that looks like so:
allUsers() {
const vm = this;
const users = this.getAll.map((item) => {
let newUser = {};
if (typeof item !== 'object') {
newUser = {
id: vm.userModel.id,
userId: vm.userModel.userId,
data: null,
tenantData: null,
};
} else {
newUser = item;
}
return newUser;
});
return users;
},
I need to insert some additional data into each newUser object, but getting that data requires 1) looping through another set of data for each newUser item and 2) getting the data returned from an axios call to a REST API endpoint:
async delete({ device, personId }) {
return await super.perform(axios.delete(ServiceUrlProvider.gmiUrl()
.concat('/person/')
.concat(personId)
.concat('/device/')
.concat(device.deviceId)));
}
Ideally I would be able to do something like this:
allUsers() {
const vm = this;
const users = this.getAll.map((item) => {
let newUser = {};
if (typeof item !== 'object') {
newUser = {
id: vm.userModel.id,
userId: vm.userModel.userId,
data: null,
tenantData: null,
};
} else {
newUser = item;
}
this.tenantApps.forEach((app) => {
userDeviceService.fetchPersonAppDevice({
id: item.id,
appCode: app.code,
})
.then((resp) => {
// Code here to add returned value to newUser object.
});
});
return newUser;
});
return users;
},
but since it is bad practice to allow async actions in computed properties, I have to try something else. Based on what I found, I'm trying vue-async-computed, and I've moved my method to the separate asyncComputed object:
asyncComputed: {
allUsers() {
const vm = this;
const users = this.getAll.map((item) => {
let newUser = {};
if (typeof item !== 'object') {
newUser = {
id: vm.userModel.id,
userId: vm.userModel.userId,
data: null,
tenantData: null,
};
} else {
newUser = item;
}
this.tenantApps.forEach((app) => {
userDeviceService.fetchPersonAppDevice({
id: item.id,
appCode: app.code,
})
.then((resp) => {
if (Array.isArray(resp.data) && resp.data.length > 0) {
newUser.hasDevice = true;
} else {
newUser.hasDevice = false;
}
});
});
return newUser;
});
return users;
},
},
My problem is getting allUsers() to wait for the returned call to userDeviceService.fetchPersonAppDevice(), since as it is now, it finishes and returns without waiting. I can't just use await on the forEach loop. How do I need to implement that call so that I can add the returned data to my newUser object?
UPDATE: Per comment by Estus Flask below, I've modified my allUsers computed value like so:
asyncComputed: {
async allUsers() {
const vm = this;
const users = this.getAll.map((item) => {
let newUser = {};
if (typeof item !== 'object') {
newUser = {
id: vm.userModel.id,
userId: vm.userModel.userId,
data: null,
tenantData: null,
};
} else {
newUser = item;
}
const devicePromises = [];
this.tenantApps.forEach((app) => {
devicePromises.push(userDeviceService.fetchPersonAppDevice({
id: item.id,
appCode: app.code,
}));
});
const devices = await Promise.all(devicePromises);
return newUser;
});
return users;
},
},
However, I get an error on the await Promise.all(devicePromises); call saying that the await operator can only be used in an async function. I've changed allUsers to be asynchronous, so why the error?

async await inside function not working properly?

I have this function, that i need to define an async function inside it:
_refetchConnection = (page) => { // query for cursor page
const refetchVariables = async (fragmentVariables) => {
let pageCursor;
if(page !== 1) {
const getAfterCursorQueryText = `
query($count: Int!, $cursor:String) {# filename+Query
viewer {
publicTodos (first: $count, after: $cursor) {
edges {
cursor
node {
id
}
}
pageInfo { # for pagination
hasPreviousPage
startCursor
hasNextPage
endCursor
}
}
}
}`;
let cursor = fragmentVariables.cursor;
let count = 5;
const getAfterCursorQuery = { text: getAfterCursorQueryText };
const result = await this.props.relay.environment._network.fetch(getAfterCursorQuery, {cursor, count});
pageCursor = result.data.viewer.publicTodos.pageInfo.endCursor;
} else if (page === 1) {
pageCursor = null;
}
return {
cursor: pageCursor,
count:5
}
}
this.props.relay.refetch(refetchVariables, null);
};
but there's no returned value on refetchVariables, it only had when I do not use async but i need to perform await for this code, and I need access on fragmentVariables:
const result = await this.props.relay.environment._network.fetch(getAfterCursorQuery, {cursor, count});
maybe making refetchVariables not an async works? but I have no idea how to code it. help? btw this is the value returned on async refetchVariables:
ƒ refetchVariables(_x2) {
return _ref3.apply(this, arguments);
}

Categories

Resources