async changeCarOwner(ctx, carNumber, newOwner) {
const carAsBytes = await ctx.stub.getState(carNumber);
if (!carAsBytes || carAsBytes.length === 0) {
throw new Error(`${carNumber} does not exist`);
}
const car = JSON.parse(carAsBytes.toString());
car.owner = newOwner
await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car)));
}
}
I keep getting an error: Unexpected end of JSON input. Why? I am trying to update an existing key-value pair in couchDb using the above code.
This error happens at this line:
const car = JSON.parse(carAsBytes.toString());
It is due to the fact that carAsBytes.toString() does not evaluates to a properly formatted JSON string. The code you show seems fine, but the error is coming from elsewhere in your code.
Debugging tip: use the debugger statement to examine variables before the faulty line, simply add a console.log(carAsBytes.toString()) before it.
Related
I'm trying to create a small plugin to make my day-to-day job easier. I have faced a very strange situation within the popup.js script. The promise function randomly refuses to get executed. I have spent some hours trying to debug or at least understand where the issue could be but without any results.
Here is the skeleton of the code:
document.addEventListener('DOMContentLoaded', function () {
// some initialization
document.getElementById("signinbutton").addEventListener("click", function(event) {
try {
// some more initialization
var user_email = '';
var advertiserId = '';
var checkibm = '';
user_email = $('#emailfield').val().trim();
advertiserId = $('#advertiseridfield').val().trim();
checkibm = $('#checkibm').is(':checked');
if (advertiserId && checkibm) {
_act = 'getTokenIdByAdvId',
_data = advertiserId
}
else if (advertiserId && !checkibm) {
_act = 'getTokenIdByAdvId',
_data = advertiserId
}
else if (user_email && validateEmail(user_email))
{
_act = 'getTokenIdByEmail',
_data = user_email
}
else
{
throw new Error("Valid input has not been provided");
}
sendMessagePromise({
act : 'getTokenIdByAdvId',
data: '16910'//encodeURIComponent(user_email)
})
.then(responseHandler)
.then(responseReplaceTokenHandler)
.then(show_ok('Done'))
.catch(failureCallback);
}
catch (error){
//doing some error catching here
});
});
The code above works perfectly. However, as soon as I fill in the real values in sendMessagePromise e.g
//_act and _data show the proper values when inspected
sendMessagePromise({
act : _act,
data: _data//encodeURIComponent(user_email)
})
the flow skips execution of sendMessagePromise and any other chained function, except the last one ".then(show_ok('Done'))", i.e the only result is the "Done" message on the screen.
I made sure the values are correct. I'm able to debug step-by-step and see the values being properly supplied. I have also put a bunch of console messages inside the chain promise functions to see where the execution gets stuck, but it seems like it doesn't even start executing sendMessagePromise.
As soon as I replace expression back to hardcoded values i.e
sendMessagePromise({
act : 'getTokenIdByAdvId',
data: '16910'//encodeURIComponent(user_email)
})
it starts working again. I'm really stuck and not sure how to debug or which steps to take further.
Please assist
I am having 10 different files and I need to read their content and merge it in one object (in NodeJS). I am successfully doing that with the code below:
const fs = require('fs');
const path = require('path');
const { promisify } = require("util");
const readFileAsync = promisify(fs.readFile);
let filePathArray = ['path/to/file/one', ... , 'path/to/file/ten'];
Promise.all(
filePathArray.map(filePath => {
return readFileAsync(filePath);
})
).then(responses => { //array of 10 reponses
let combinedFileContent = {};
responses.forEach((itemFileContent, index) => {
let tempContent = JSON.parse(itemFileContent);
//merge tempContent into combinedFileContent
}
});
But what I wonder is, how to catch if there is some error while trying to read the files? When reading a single file, this works like:
fs.readFile(singleFilePath, (singleFileErr, singleFileContent) => {
if (singleFileErr) {
//do something on error, while trying to read the file
}
});
So my question here is, how can I access to the error inn the first code snippet, which corresponds to singleFileErr from this second code snippet?
The issue I am facing is: in case some of the files does not exists, I want to check the error and to skip this file, but since I can not detect the error with current implementation, my whole block crashes and I am not able to merge the other 9 files because of this one. I want to use the error check I mentioned in the second snippet.
Check out the Promise.allSettled function, which will run every Promise passed to it, and will tell you at the end which ones succeeded and which ones failed.
Maybe try something like this:
in the map() callback, return a promise that resolves to null if the file is not found.
Introduce a middle stage in the promise chain filtering out null responses.
This would look something like this:
Promise.all(
filePathArray.map(filePath => {
return readFileAsync(filePath).catch(function(error){
if(isErrorFileDoesNotExist(error)) return null
throw error;
})
});
).then(responses => {
return responses.filter(response => response != null)
})
.then(filteredResponses => {
// .. do something
});
Would that work for you? Note this presupposes you are actually able to discriminate between missing file errors from other errors the promise returned by readFileAsync() may reject - presumably via the isErrorFileDoesNotExist() function in this snippet.
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.
When I try to run a function
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.checkPostsRef = functions.https.onRequest((request, response) => {
const postId = 'foo'
admin.database().ref('/posts/' + postId).once('value', snapshot => {
if !snapshot.exists() {
console.log("+++++++++ post does not exist +++++++++") // I want this to print
return
}
});
});
I keep getting an error of Parsing error: Unexpected token snapshot:
Once I comment out if snapshot.exists() { .... } everything works fine.
I'm following this link that says there is an .exists() function, so why am I having this issue?
Good to see how you got it working Lance. Your conclusion on the return being the cause is wrong though, so I'll explain the actual cause below.
The problem is in this code:
if !snapshot.exists() ...
In JavaScript you must have parenthesis around the complete condition of an if statement. So the correct syntax is:
if (!snapshot.exists()) ...
In Swift those outer parenthesis are optional, but in JavaScript (and al other C based languages that I know of), they are required.
turns out it was the return; statement that was causing the problem. I had to use an if-else statement instead.
EDIT As #FrankvanPuffelen pointed out in the comments below the question and his answer, this issue wasn't about the return statement, it was about the way i initially had the !snapshot.exists(). Because it wasn't wrapped in parentheses (!snapshot.exists()) which was causing the problem. So it wasn't the return statement, I know very little Javascript and used the wrong syntax.
if (!snapshot.exists()) {
console.log("+++++++++ post does not exist +++++++++");
} else {
console.log("--------- post exists ---------");
}
FYI I'm a native Swift developer and in Swift you don't need to wrap anything in parentheses. In Swift you can do this:
let ref = Database.database().reference().child("post").child("foo")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if !snapshot.exists() {
print("+++++++++ post does not exist +++++++++")
return
}
})
I am new to MongoDB/backend and have spent a couple of hours on this one. Hoping/expecting there is a silly mistake here!
Essentially, in the process of adding new users to the db, I want to check one of the specified values (the "position code(s)") against a list of acceptable codes. I retrieve these acceptable position codes via an async call and then use an underscore method to compare the specified position code(s) against the acceptable ones. If any are found, I throw an error.
Multiple users can be added at a time and each user can have multiple roles. So both of these are array types.
The most recent thing i've tried is simply using the "throw new Error()" methodology since my understanding is that this should get picked up by the Express middleware. But it's not working. The error message I specify in the error object IS getting printed in the console, but in a "UnhandledPromiseRejectionWarning" error. When running this in Postman, Postman just doesn't return anything (basically appears like it's loading and then says could not get a response").
I also tried wrapping this in a try catch block.
I also tried passing the error to a next() method.
router.route('/add').post(async (req, res) => {
let
newAdults = [],
roleCodes = await Role.find()
.then(roles => _.pluck(roles, "code"))
.catch(err => res.status(400).json('Error: ' + err));
req.body.forEach((el, id) => {
let
firstName = el.firstName,
lastName = el.lastName,
emailAddress = el.emailAddress,
username = el.username,
roles = el.roles;
// one thing we need to lookout for is if an invalid role code is being used.
// here we compare role codes associated with the new adult and all approved
// role codes. this will identify invalid role codes
let invalidCodes = _.difference(_.pluck(roles, "code"), roleCodes)
if (invalidCodes.length > 0)
throw new Error(`Role code(s) ${invalidCodes} for ${firstName} ${lastName} are invalid.`)
Ultimately I want to just return the message I have in my error object.
Since you are throwing the error without handling it in your API, it remains in incomplete state and you get could not get a response error in POSTMAN.
You can try this,
Create new error object array and store the error messages in that object rather then throwing the error.
You can return this error object array in response in case this array has values.
Here is the updated snippet:
router.route('/add').post(async (req, res) => {
let
newAdults = [],
roleCodes = await Role.find()
.then(roles => _.pluck(roles, "code"))
.catch(err => res.status(400).json('Error: ' + err));
let errorArray = [];
req.body.forEach((el, id) => {
let
firstName = el.firstName,
lastName = el.lastName,
emailAddress = el.emailAddress,
username = el.username,
roles = el.roles;
// one thing we need to lookout for is if an invalid role code is being used.
// here we compare role codes associated with the new adult and all approved
// role codes. this will identify invalid role codes
let invalidCodes = _.difference(_.pluck(roles, "code"), roleCodes)
if (invalidCodes.length > 0) {
errorArray.push(`Role code(s) ${invalidCodes} for ${firstName} ${lastName} are invalid.`);
}
if (errorArray && errorArray.length) {
res.status(400).json(errorArray)
}