Javascript async function never returns - javascript

I'm trying to run a simple program that pulls from Redis and inserts into a database. This program never seems to exit, can someone point me in the right direction?
require('newrelic')
const client = require('./config/redis')
const models = require('./models')
const sequelize = require('sequelize')
async function flushTweets() {
try {
var tweets = await client.lrangeAsync('writer', 0, 100)
client.ltrim('writer', 0, 100)
if (tweets && tweets.length > 0) {
tweets = tweets.map(tweet => JSON.parse(tweet))
models.Tweet.bulkCreate(tweets, { returning: true });
for (var i = 0; i < tweets.length; ++i) {
models.User.update(
{ numTweets: sequelize.literal(`"Users"."numTweets" + 1`) },
{ where: { id: tweets[i].user.id }
});
}
}
} catch (e) {
}
}
flushTweets();

Related

Return empty array in Fastify handler with async/await function

I'm trying to make a web3 wallet with Moralis with Fasitify in back and VueJS in front.
(I would like to say that I already do this in web client (vuejs) and everything works well!)
In my back, I fetch all the asset from user. It works, I get them all well and I can send them back to the front
But I need to process/sort the data to recover only part of it and send it to the front to avoid doing too much treatment at the front and reduce your workload.
I do that :
*handlers/token.js*
const getTokenBalances = async () => {
let userTokens;
const options = {
chain: "bsc",
address: "0x935A438C29bd810c9aBa2F3Df5144d2dF4F3c0A0",
};
userTokens = await Moralis.Web3API.account.getTokenBalances(options);
return userTokens;
};
and if I return userTokens, I had it in Postman. But now, I do something like :
const getTokenBalances = async (tokens) => {
let userTokens;
let userBalances = [];
const options = {
chain: "bsc",
address: "0x935A438C29bd810c9aBa2F3Df5144d2dF4F3c0A0",
};
userTokens = await Moralis.Web3API.account.getTokenBalances(options);
userTokens.forEach((token) => {
if (
!token.name.match(/^.*\.io/) &&
!token.name.match(/^.*\.IO/) &&
!token.name.match(/^.*\.net/) &&
!token.name.match(/^.*\.Net/) &&
!token.name.match(/^.*\.com/) &&
!token.name.match(/^.*\.org/)
) {
getTokenPair(token).then((value) => {
if (value > 2) {
checkTokenPrice(token).then((price) => {
if (price > 0.001) {
userBalances.push(token);
}
});
}
});
}
});
userBalances.sort((a, b) => {
return b.total_value_usd - a.total_value_usd;
});
return userBalances;
};
userBalances its always empty in my response in Postman (And I don't understand why ?)
The getTokenPair function :
const getTokenPair = async (token) => {
const BNBTokenAddress = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"; //BNB
const options = {
token0_address: token.token_address,
token1_address: BNBTokenAddress,
exchange: "pancakeswapv2",
chain: "bsc",
};
try {
const pairAddress = await Moralis.Web3API.defi.getPairAddress(options);
let amount = 0;
//console.log("token pairAddress : " + pairAddress.pairAddress);
if (pairAddress.token1.symbol === "BUSD") {
try {
let reserve = await getPairReserves(pairAddress.pairAddress);
amount += reserve / 10 ** 18;
} catch (err) {
console.log("error getReservesBUSD : " + err);
}
}
if (pairAddress.token1.symbol === "WBNB") {
try {
let reserve = await getPairReserves(pairAddress.pairAddress);
amount += reserve / 10 ** 18;
} catch (err) {
console.log("error getReservesWBNB : " + err);
}
}
//console.log("amount : " + amount)
return amount;
} catch (err) {
console.log("error getPair : " + err);
}
};
and the checkTokenPrice function :
const checkTokenPrice = async (token) => {
let price;
const options = {
address: token.token_address,
chain: "bsc",
exchange: "PancakeSwapv2",
};
try {
const priceToken = await Moralis.Web3API.token.getTokenPrice(options);
price = priceToken.usdPrice.toFixed(7);
token.price = priceToken.usdPrice.toFixed(7);
token.balance = insertDecimal(token.balance, token.decimals);
token.total_value_usd = (token.balance * token.price).toFixed(2);
return price;
} catch (err) {
console.log("error tokenPrice : " + err);
}
};
They are await method in all the function I use so maybe there is a connection.
Thanks for you help !
**** EDIT *****
I solve my problem like this :
const getTokenBalances = async () => {
let userTokens;
let userBalances = [];
const options = {
chain: "bsc",
address: "0x935A438C29bd810c9aBa2F3Df5144d2dF4F3c0A0",
};
userTokens = await Moralis.Web3API.account.getTokenBalances(options);
for (token of userTokens) {
if (
!token.name.match(/^.*\.io/) &&
!token.name.match(/^.*\.IO/) &&
!token.name.match(/^.*\.net/) &&
!token.name.match(/^.*\.Net/) &&
!token.name.match(/^.*\.com/) &&
!token.name.match(/^.*\.org/)
) {
let value = await getTokenPair(token);
if(value > 2) {
let price = await checkTokenPrice(token);
if (price > 0.001) {
userBalances.push(token);
}
}
}
}
return userBalances;
};
Thanks for the help ! ;)

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.

How to measure the time of several calls of async function

I have a problem with understanding how do async functions in js work. So I need to call async function for 5 times and measure the duration of every execution. In the end I should have an array with 5 time values.
I have smth like this
for (let i = 0; i < 5; i++) {
const run = async () => {
await test(thisTest, filename, unitTestDict);
};
measure(run).then(report => {
// inspect
const {tSyncOnly, tSyncAsync} = report;
// array.push(tSyncAsync)
console.log(`∑ = ${tSyncAsync}ms \t`);
}).catch(e => {
console.error(e)
});
}
Here I found the realization of time measure function:
class Stack {
constructor() {
this._array = []
}
push(x) {
return this._array.push(x)
}
peek() {
return this._array[this._array.length - 1]
}
pop() {
return this._array.pop()
}
get is_not_empty() {
return this._array.length > 0
}
}
class Timer {
constructor() {
this._records = new Map
/* of {start:number, end:number} */
}
starts(scope) {
const detail =
this._records.set(scope, {
start: this.timestamp(),
end: -1,
})
}
ends(scope) {
this._records.get(scope).end = this.timestamp()
}
timestamp() {
return performance.now()
}
timediff(t0, t1) {
return Math.abs(t0 - t1)
}
report(scopes, detail) {
let tSyncOnly = 0;
let tSyncAsync = 0;
for (const [scope, {start, end}] of this._records)
if (scopes.has(scope))
if (~end) {
tSyncOnly += end - start;
tSyncAsync += end - start;
const {type, offset} = detail.get(scope);
if (type === "Timeout")
tSyncAsync += offset;
}
return {tSyncOnly, tSyncAsync}
}
}
async function measure(asyncFn) {
const stack = new Stack;
const scopes = new Set;
const timer = new Timer;
const detail = new Map;
const hook = createHook({
init(scope, type, parent, resource) {
if (type === 'TIMERWRAP') return;
scopes.add(scope);
detail.set(scope, {
type: type,
offset: type === 'Timeout' ? resource._idleTimeout : 0
})
},
before(scope) {
if (stack.is_not_empty) timer.ends(stack.peek());
stack.push(scope);
timer.starts(scope)
},
after() {
timer.ends(stack.pop())
}
});
return await new Promise(r => {
hook.enable();
setTimeout(() => {
asyncFn()
.then(() => hook.disable())
.then(() => r(timer.report(scopes, detail)))
.catch(console.error)
}, 1)
})
}
I can call it inside the loop and get console.log with time for every iteration:
measure(run).then(report => {
// inspect
const {tSyncOnly, tSyncAsync} = report;
// array.push(tSyncAsync)
console.log(`∑ = ${tSyncAsync}ms \t`);
}).catch(e => {
console.error(e)
});
But when I try to push this console values to array, nothing comes out, the array remains empty. Is there a way to fill it in?

AdonisJS - SyntaxError. Unexpected character ' '

I am trying to fetch all talent resource from the database but when I tried the endpoint on Postman, it returned a SyntaxError. Unexpected character '' error. I dont know where that character is coming from as postman hinted that the error is on Line 66 of my controller, but on checking the line 66 is an empty/blank line.
What could possibly cause this error?
My controller code (the method the API is calling is below)
async searchTalent({ request, response }) {
try {
const params = request.except('projectId');
let matchedTalents = [];
let talentIds = [];
const {tools, fullname} = params;
if(tools) {
const find = await Database.raw("SELECT * FROM pro WHERE MATCH tools AGAINST ('"+ tools +"' IN NATURAL LANGUAGE MODE)");
const talents = find[0];
if(talents) {
for(let t = 0; t < talents.length; t++) {
const talent = talents[t];
if(talent.active == true) {
const user = await User.query().where({id: talent.userId, active: true, type: 'talent', isDeleted: false}).first();
if(user) {
if(talentIds.length > 0) {
if(talentIds.includes(talent.id) === false) {
user.profile = talent;
talentIds.push(talent.id);
matchedTalents.push(user);
}
} else {
user.profile = talent;
talentIds.push(talent.id);
matchedTalents.push(user);
}
}
}
}
}
// for (let i = 0; i < tools.length; i++) {
// const tool = tools[i];
// }
} else if(fullname) {
const getUsers = await User.query().where('first_name', 'LIKE', '%%' + fullname + '%%').orWhere('last_name', 'LIKE', '%%' + fullname + '%%').where({ active: true}).orderBy('id', 'desc').get();
for (let i = 0; i < getUsers.length; i++) {
const user = getUsers[i];
if(user.type == 'talent')
{
const talent = await Pro.query().where({userId: user.id}).first();
if(talent)
{
user.profile = talent;
matchedTalents.push(user);
}
}
}
}
​
const data = matchedTalents;
​
return response.json({
data: data,
message: data.length + ' Talents fetched',
error: false
})
} catch (e) {
Event.fire('log::error', e.message)
return response.json({
data: [],
message: e.message,
error: true
})
}
}
I have tried searching and fixing since yesterday but all stackoverflow answers don't seem to address this issue.

How to return Boolean properly in different NodeJS files?

So I have files inside the following folder:
app/controller/token.js
app/controller/news.js
token.js:
"use strict";
var connection = require("../con");
exports.isTokenExists = function(token) {
var checkToken = "SELECT COUNT(`id`) AS 'total' FROM `user` WHERE `token` = '" + token + "'";
var isExists = false;
var count;
var checkResult;
connection.query(checkToken, function(error, rows) {
if (!error) {
checkResult = JSON.parse(JSON.stringify(rows));
for (var i = 0; i < checkResult.length; i++) {
var row = rows[i];
count = row.total;
}
if (count > 0) {
isExists = true;
}
}
});
return isExists;
};
news.js:
"use strict";
var response = require("../response/responses");
var connection = require("../con");
var getToken = require("./token");
exports.news = function(req, res) {
response.send(false, "News API", null, res);
};
exports.allNews = function(req, res) {
var checkTokenExists = getToken.isTokenExists("75d12cc4dc07608d5b87a6cba33cac056df1239c");
if (checkTokenExists) {
var allNewsQuery = "SELECT a.`id`, b.`title` AS `category`, a.`title`, a.`description`, a.`content`, a.`image`, a.`created_date` FROM `news` AS a LEFT JOIN `news_category` AS b ON a.`id_news_category` = b.`id` ORDER BY `created_date` DESC LIMIT 20";
connection.query(allNewsQuery, function(error, rows) {
if (error) {
response.send(true, "" + error, null, res);
} else {
var data = [];
var newsData = JSON.parse(JSON.stringify(rows));
for (var i = 0; i < newsData.length; i++) {
var row = rows[i];
data[i] = {
id: row.id,
idCategory: row.idCategory,
category: row.category,
title: row.title,
description: row.description,
image: row.image,
createdDate: row.created_date
};
}
response.send(false, "News is not empty", data, res);
}
});
} else {
response.send(true, "Error: Token not found", checkTokenExists, res);
}
};
I always getting false value from isTokenExists meanwhile the token is exists in the table.
How do I get true response if the token is exist and how do I get false response if the token is not exists in table?
Any help will be much appreciated.
Regards.
The issue here is that connection.query accepts a callback, but the rest of your code will move passed that without awaiting the result, which is why your isExists always returns false. You can fix this by encapsulating the query with a Promise like this:
"use strict";
const connection = require("../con");
exports.isTokenExists = async function(token) {
const checkToken = "SELECT COUNT(`id`) AS 'total' FROM `user` WHERE `token` = ?";
return new Promise((resolve, reject) => {
connection.query(checkToken, token, function (error, results) {
if (error) return reject(error);
return resolve(results.length > 0);
});
});
};
I also simplified the logic in the callback a bit.
Then, in news.js await the result like this:
exports.allNews = async function(req, res) {
getToken.isTokenExists("75d12cc4dc07608d5b87a6cba33cac056df1239c")
.then(result => {
if (result === true) {
//place your code for handling if the token exists here
}
else {
//place your code for handling if the token does not exist
}
})
.catch(err => {
//handle error
});
}
You are missing async / await concept. You need to wait until your query executes.
1) Write a promise function
export.getCount = function(query) {
return new Promise((res, rej) => {
let count = 0;
connection.query(checkToken, function(error, rows) {
if (!error) {
checkResult = JSON.parse(JSON.stringify(rows));
for (var i = 0; i < checkResult.length; i++) {
var row = rows[i];
count = row.total;
}
}
return res(count);
})
}
2) Write async function which supports await operations
exports.isTokenExists = async function(token) {
var query = "SELECT COUNT(`id`) AS 'total' FROM `user` WHERE `token` = '" + token + "'";
let count = await getCount(query)
return count > 0; // Returns true if count is > 0
};

Categories

Resources