Hyperledger node.js failed to parse null - node.js

can somebody help with error which appears on HL Composer?
Error content: Error: SyntaxError: Failed to parse null: Unexpected token (377:39)
Line 377 is: let exists = await accounts.exists(element.destinationAcc)
let accounts = await getAssetRegistry(ns + '.Account');
let transactions = await getAssetRegistry(ns + '.Transactions');
let allTransactions = await query('pendingTransactions');
let allAccounts = await accounts.getAll();
if (allTransactions.length() > 0) {
allTransactions.forEach(element => {
if (element.status == 'PENDING') {
let exists = await accounts.exists(element.destinationAcc);
if (exists) {
let destAcc = await allAccounts.find(element.destinationAcc);

This is a pretty standard mistake that javascript developers make and isn't related to hyperledger composer at all.
You are trying to perform an await within a method that hasn't been declared async. HOWEVER even if you do add the keyword async to the method that you have declared inside the forEach declaration it still won't work, due to the way forEach works.
So for you the solution is, don't use the forEach method of an array to try to run an anonymous function with an await in it. Use an alternative method to iterate the allTransactions array such as a for loop.

Related

Discord vs bot 13 not able to assign roles giving error Cannot read properties of undefined (reading 'guild')

I am using discord js v13.6. I have written in my code where after using a slash command user is assigned many roles which are stored in a array named rolenumber. The problem is I am getting this error every time
await client.users.fetch(memberId).then((user,interaction) => {
user.send("Give me a few moments while I verify your details");
(async function(user){
let RoleArray = rolenumber.split(",");
//let guild = client.guilds.cache.get(guildNumber);
//let member = await client.users.fetch(msg);
for(let num of RoleArray) {
//console.log("Roles Inside a for loop",num);
let role = interaction.guild.roles.cache.get(num);
let data = await user.roles.add(role).catch(console.error);
//user.roles.add(num).catch(console.error);
}
let welcomeMessage = 'Welcome <#'+ user.id +'>, you are now officially part of channel.';
const channelMessage = await client.channels.cache.get(channelNumber);
channelMessage.send(welcomeMessage);
})();
here the guildNumber is a guild Number which is hidden for security reason from the question. I am getting this as error message:
let role = interaction.guild.roles.cache.get(num);
^
TypeError: Cannot read properties of undefined (reading 'guild')
at E:\OutscalGit\DiscordBot\index.js:200:44
at processTicksAndRejections (node:internal/process/task_queues:96:5)
interaction is undefined
Are you sure, interaction is passed to here?
you can use it but it not perfect
let role = interaction?.guild?.roles?.cache?.get(num);
Promise.prototype.then's fulfillment callback only takes 1 argument.
await client.users.fetch(memberId).then((user) => {
user.send("Give me a few moments while I verify your details")
// ...
})
Assuming interaction is already defined above, it should work

Why await within async function doesn't work for fs modules?

I am trying to read a sample.json file through my js code. First my program checks for sample.json within every folder in the specified path. And it reads the sample.json if available and fetches the data. But the await used doesn't work as expected and simply passes the empty object to the calling function before the async functions completes it execution. I have attached the image for the issue.
async function getAvailableJson(filesPath) {
let detectedJson = {};
let folders = await fs.promises.readdir(filesPath);
folders.forEach(async function(folder) {
await fs.promises.access(path.join(filesPath, folder, "Sample.json")).then(async function() {
jsonData = await fs.promises.readFile(path.join(filesPath, folder ,"Sample.json"))
const directory = JSON.parse(jsonData)
const hashvalue = Hash.MD5(jsonData)
detectedJson[directory["dirName"]] = {
name: directory["dirName"],
version: directory["dirVersion"],
hash: hashvalue
}
console.log(detectedJson);
}).catch(function(err) {
if(err.code === "ENOENT")
{}
});
});
return detectedJson;
}
I don't want to use any sync functions since it creates unnecessary locks. I have also tried with fs.readdir, fs.access and fs.readFile functions. Could someone point out what I am doing wrong here since I am new to Node.js thanks in advance.
Sample Image
Change your .forEach() to use for/of instead and generally simplify by not mixing await and .then().
async function getAvailableJson(filesPath) {
let detectedJson = {};
let folders = await fs.promises.readdir(filesPath);
let detectedJson = {};
for (let folder of folders) {
let file = path.join(filesPath, folder, "Sample.json");
try {
let jsonData = await fs.promises.readFile(file);
const directory = JSON.parse(jsonData);
const hashvalue = Hash.MD5(jsonData);
detectedJson[directory["dirName"]] = {
name: directory["dirName"],
version: directory["dirVersion"],
hash: hashvalue
};
} catch (err) {
// silently skip any directories that don't have sample.json in them
// otherwise, throw the error to stop further processing
if (err.code !== "ENOENT") {
console.log(`Error on file ${file}`, err);
throw err;
}
}
console.log(detectedJson);
}
return detectedJson;
}
Summary of Changes:
Replace .forEach() with for/of.
Remove .then() and use only await.
Remove .catch() and use only try/catch.
Remove call to fs.promises.access() since the error can just be handled on fs.promises.readFile()
Add logging if the error is not ENOENT so you can see what the error is and what file it's on. You pretty much never want to silently eat an error with no logging. Though you may want to skip some particular errors, others must be logged. Rethrow errors that are not ENOENT so the caller will see them.
Declare and initialize all variables in use here as local variables.
.forEach() is not promise-aware so using await inside it does not pause the outer function at all. Instead, use a for/of loop which doesn't create the extra function scope and will allow await to pause the parent function.
Also, I consider .forEach() to be pretty much obsolete these days. It's not promise-aware. for/of is a more efficient and more generic way to iterate. And, there's no longer a need to create a new function scope using the .forEach() callback because we have block-scoped variables with let and const. I don't use it any more.
Also, I see no reason why you're preflighting things with fs.promises.access(). That just creates a race condition and you may as well just handle whatever error you get from fs.promises.readFile() as that will do the same thing without the race condition.
See also a related answer on a similar issue.

Discord JS - TypeError: Cannot read property 'setChannel' of undefined

I'm trying to use multiple user mentions and message.mention.members.first() cannot do this. So I did some digging and found this function from Parsing Mention Arguments:
function getUserFromMention(mention) {
if (!mention) return;
if (mention.startsWith('<#') && mention.endsWith('>')) {
mention = mention.slice(2, -1);
if (mention.startsWith('!')) {
mention = mention.slice(1);
}
return client.users.cache.get(mention);
}
}
When I try to use this function I get the "Discord JS - TypeError: Cannot read property 'setChannel' of undefined" here is the code causing the error
let channel = client.channels.cache.find(channel => channel.name === args[0]);
const user1 = getUserFromMention(args[1]);
const user2 = getUserFromMention(args[2]);
message.member.voice.setChannel(channel.id);
user1.voice.setChannel(channel.id);
user2.voice.setChannel(channel.id);
This code Is meant to move Myself and mentioned users to selected Voice Channel it works perfectly fine when using message.mention.members.first() but can only handle one out of two of the mentioned users.
I was wondering if there was a fix for my current error or if there is another way I should be working this out?
Remember that,
message.mentions.members- Returns a GuildMember whereas
client.users.cache.get - Returns a User
You can only move/disconnect GuildMembers across VCs.
Therefore you can use message.mentions.members, which returns a Collection of all mentioned Users.
let channel = client.channels.cache.find(channel => channel.name === args[0]);
message.member.voice.setChannel(channel.id);
message.mentions.members.each(u => {
u.voice.setChannel(channel.id);
})
The problem can be, that the user is not in cache, so you must use GuildMemberManager#fetch(id). Problem is, that this function is async. The easiest solution is to make getUserFromMention and the functions where you use it async and use await.

History of asset in Hyperledger Fabric

I am using node.js to write chaincode and I want to get the history of drug in pharmaceutical supply chain. I deployed chaincode, invoked manufacture and buy contract which modifies the drug's current state from one owner to another owner. Infact, I just modified commercial paper chaincode for this. The change in owner is reflected in couchdb database. But when I try to get the history of drug by drug key it doesn't work as expected.
Code I used
const promiseOfIterator = this.ctx.stub.getHistoryForKey(drugKey);
const results = [];
for await (const keyMod of promiseOfIterator) {
const resp = {
timestamp: keyMod.timestamp,
txid: keyMod.tx_id
}
if (keyMod.is_delete) {
resp.data = 'KEY DELETED';
} else {
resp.data = keyMod.value.toString('utf8');
}
results.push(resp);
}
return results;
When I printed the results, it gives: []
And when I do this: Drug.fromBuffer(getDrugHistoryResponse); and print it, it gives Drug { class: 'org.medicochainnet.drug', key: ':', currentState: null }
How to make this work? What am I doing wrong here? Please help me.
the function
ctx.stub.getHistoryForKey(drugKey);
is an asynchronous function. So you need to add await
const promiseOfIterator = await this.ctx.stub.getHistoryForKey(drugKey);
Then you can iterate over the result.
I have done it in a demo like that:
const promiseOfIterator = await this.ctx.stub.getHistoryForKey(drugKey);
const results = [];
while(true){
let res = await promiseOfIterator.next();
//In the loop you have to check if the iterator has values or if its done
if(res.value){do your actions}
if(res.done){
// close the iterator
await promiseOfIterator.close()
// exit the loop
return results
}
}
Check the Mozilla Documentation for more information about Iterators in Javascript. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators

Click on every 'a' tag in page puppeteer

I am trying to get puppeteer to go to all a tags in a page and load them, add them to an array and return it. My puppeteer version is 1.5.0. Here is my code:
module.exports.scrapeLinks = async (page, linkXpath) => {
page.waitForNavigation();
linksElement = await page.$x(linkXpath);
var url_list_arr = [];
console.log(linksElement.length);
i=1;
for(linksElementItem in linksElement)
{
const linksData = await page.$x('(' + linkXpath + ')[' + (i + 1) +']');
if (linksData.length > 0) {
linksData[0].click();
console.log(page.url());
url_list_arr.push(page.url());
}
else {
throw new Error('Link not found');
}
}
return url_list_arr;
};
However with this code, I get an
UnhandledPromiseRejectionWarning: Error: Node is either not visible or
not an HTMLElement
I also found out through the docs that is not possible to use the xpath on the page.click function. Is there anyway to achieve this?
It is also okay if there is a function to get all the link from a page, but I couldn't find it in the docs.
To get a handle on all a-tags in an array:
const aTags= await page.$$('a')
Loop through them with:
for (const aTag of aTags) {...}
Inside the loop you can interact with each of these elementHandle separately.
Note that
await aTag.click()
will destroy (garbage collect) all elementHandles when the page context is navigated. In this case you need a workaround like loading the initial page inside a loop to always start with a fresh instance.

Resources