In my meteor project, I want to use generic functions in my Meteor.methods
(Mostly because I don't want users to call this functions from the client).
I'm defining this function in another file :
const ldapPing = (callback) => {
try {
ldapAuth.client = createClient({
url: Meteor.settings.private.LDAP.URL,
});
ldapAuth.client.on('error', () => {
throw new Meteor.Error('500', 'Cant join.');
});
callback(null, true);
} catch (exception) {
callback(exception, null);
}
};
And I'm calling it in my meteor methods like this :
'test.ldap': function testLdap() {
try {
const future = new Future();
ldapPing((error, result) => {
console.log('ERROR : ' + error);
console.log('RESULT : ' + result);
if (error) {
future.throw(error);
} else {
future.return(true);
}
});
return future.wait();
} catch (exception) {
throw exception;
}
},
However, the Meteor.error is not returned to the Meteor method and is immediatly throw from the simple function ldapPing, which stops meteor with "Exited with code: 1".
Any idea why ?
(This example is made for this question, ofc in this case there is no benefits to externalize this function)
Related
I am writing middleware code for setting up authentication and token validation in my nextjs app. I am using throw instead of returning value from the helper function.
But throw (last statement) is not working in the following code:
async function validate(request: NextRequest) {
const tokenid = "test";
if (tokenid) {
try {
// in case of error
throw new Error("test");
} catch (error) {
console.error("validate: ", error);
}
}
throw new Error("tokenId validation failed");
}
This function is called within another function and where the last statement is simply ignored.
export async function googleAuthValidate(request: NextRequest) {
let response = NextResponse.next();
try {
validate(request);
console.log("throw didnt go into catch");
} catch (error) {
console.error(error);
response = NextResponse.rewrite("/unauthorized");
} finally {
return response;
}
}
I have created a repository for this issue for easy reproduction: repo
I have a meteor call and meteor method. When I throw Meteor error then it is not caught inside meteor call's error but instead in response
Here is my meteor method
Meteor.call("updateFtIndex", id, $(`#idx-${id}`).val(), function (error, result) {
if (error) {
console.log('error: ', error.reason);
}
else {
console.log('result', result);
}
})
and here is my meteor method
Meteor.methods({
updateFtIndex: function (_id, index) {
try {
let isIndexExists = Meteor.users.findOne({_id, "profile.featuredProviderIndex": index }, {fields:
{"profile.featuredProviderIndex": 1}});
if(isIndexExists){
console.log('isIndexExists: ', isIndexExists);
throw new Meteor.Error( 400, "Sorted index already exist !!!");
}
else {
console.log("else");
return Meteor.users.update({_id}, { $set: { "profile.featuredProviderIndex": index } });
}
} catch (error) {
return error
}
}
})
And I get the thrown error inside result of meteor call
Can somebody tell me what is wrong with the code ?
You are catching the throw and your catch is returning the error but the better way to return an error to the front is your change it to this:
try {
let isIndexExists = Meteor.users.findOne({_id, "profile.featuredProviderIndex": index }, {fields: {"profile.featuredProviderIndex": 1}});
if(isIndexExists){
console.log('isIndexExists: ', isIndexExists);
throw new Meteor.Error( 400, "Sorted index already exist !!!");
}
else {
console.log("else");
return Meteor.users.update({_id}, { $set: { "profile.featuredProviderIndex": index } });
}
} catch (e) {
throw new Meteor.Error(400, e.toString());
}
You are returning error instead of throwing it from catch block.
I'm using the AWS Javascript SDK and I'm following the tutorial on how to send an SQS message. I'm basically following the AWS tutorial which has an example of the sendMessage as follows:
sqs.sendMessage(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.MessageId);
}
});
So the sendMessage function uses a callback function to output whether the operation was successful or not. Instead of printing to the console I want to return a variable, but every value I set is only visible within the callback function, even global variables like window.result are not visible outside the callback function. Is there any way to return values outside the callback?
The only workaround I've found at the moment is to set a data attribute in an HTML element, but I don't think it's really elegant solution.
I would suggest to use Promises and the new async and await keywords in ES2016. It makes your code so much easier to read.
async function sendMessage(message) {
return new Promise((resolve, reject) => {
// TODO be sure SQS client is initialized
// TODO set your params correctly
const params = {
payload : message
};
sqs.sendMessage(params, (err, data) => {
if (err) {
console.log("Error when calling SQS");
console.log(err, err.stack); // an error occurred
reject(err);
} else {
resolve(data);
}
});
});
}
// calling the above and getting the result is now as simple as :
const result = await sendMessage("Hello World");
I'm having trouble understanding the output printed why executing this code :
1
2
Unhandled rejection Error: Callback was already called.
It seems like both then and catch are executed when the query is successful.
Any idea ?
Cheers
async.series([
function(callback) {
db.none(query)
.then(function () {
return callback(null, true);
})
.catch(function (err) {
return callback(err, null);
});
},
function(callback) {
db.any(query)
.then(function (data) {
console.log('1')
return callback(null, data);
})
.catch(function (err) {
console.log('2')
console.log(err);
return callback(err, null);
});
}
],
function(err, results) {
if (results && !results[1].isEmpty()) {
// do something
}
});
EDIT :
TypeError: results[1].isEmpty is not a function
It seems like the problem come from the rest of the code and was just a simple undefined function error, thanks.
But i still don't understand something : why is this error catched inside the second query instead of outside the async queries ?
I'm the author of pg-promise.
You should never use async library with pg-promise, it goes against the concept of shared/reusable connections.
Implementation with proper use of the same connection, via a task:
db.task(t => {
return t.batch([
t.none(query1),
t.any(query2)
]);
})
.then(data => {
// data[0] = null - result of the first query
// data[1] = [rows...] - result of the second query
callback(null, data); // this will work, but ill-advised
})
.catch(error => {
callback(error, null); // this will work, but ill-advised
});
See also: Chaining Queries.
However, in your case it looks like when you call the successful callback(null, data), it throws an error, which in turn results in it being caught in the following .catch section. To test this, you can change your promise handler like this:
.then(data => {
callback(null, data);
}, error => {
callback(error, null);
});
It should normally throw an error about Promise missing .catch because you threw an error while in .then and there is no corresponding .catch chained below, which you can also check through this code:
.then(data => {
callback(null, data);
}, error => {
callback(error, null);
})
.catch(error => {
// if we are here, it means our callback(null, data) threw an error
});
P.S. You really should learn to use promises properly, and avoid any callbacks altogether. I only provided an example consistent with your own, but in general, converting promises into callbacks is a very bad coding technique.
This is what happens:
callback(null, data) is called within the context of the .then();
async notices that this was the last item of the series, so it calls the final handler (still within the context of the .then());
the final handler throws an error;
because the code runs in the context of .then(), the promise implementation catches the error and calls the .catch();
this calls the callback again;
PoC:
const async = require('async');
async.series([
callback => {
Promise.resolve().then(() => {
callback(null);
}).catch(e => {
callback(e);
});
}
], err => {
throw Error();
})
Have you try to define your function externally:
function onYourFunction() {
console.log('Hi function');
}
and than do:
.then(onYourFunction) //-->(onYourFunction without parentheses )
Unfortunately i don't use pg-promise but i can advise promise
at this point i create all promises that are necessary:
function createPromise(currObj) {
return new Promise(function (resolve, reject) {
currObj.save(function (errSaving, savedObj) {
if(errSaving){
console.log("reject!");
return reject(errSaving, response);
}
console.log('currObj:' + currObj);
return resolve(savedObj);
});
});
}
and then in cascades:
var allPromiseOs = Promise.all(promise1, promise2, promise3);
We're using the Q promise library in our node API, but allow functions to be called via callbacks.
For example:
function foo(cb) {
Q.fcall(function () {
return true;
}).then(function (result) {
return cb(null, result);
}).catch(function (err) {
return cb(err, null);
});
}
When I run my mocha unit tests, if there is an exception in the callback, it results in the the callback being called twice.
For example:
var called = 0;
foo(function (err, res) {
called++;
console.log('err: ' + err);
console.log('res: ' + res);
console.log('called: ' + called);
throw Error(throw Error from foo!');
});
This gives the following result:
err: null
res: true
called: 1
err: Error: throw Error from foo!
res: null
called: 2
One approach we found was to do the following:
function foo2(cb) {
var _result, _err;
Q.fcall(function () {
return true;
}).then(function (result) {
_result = result;
}).catch(function (err) {
_err = err;
}).finally(function () {
_.defer(cb, _err, _result);
});
}
The idea was to have one place where the callback would be called and try to prevent developer errors by enforcing the defer to clear the call stack.
With this approach, our callback is called once, and any errors (or in our case, asserts) get handled directly by the caller.
Is there a better technique we can use? I feel like this is a pretty common scenario, so I'd imagine there exists a cleaner solution...
Modify your foo function to handle both the fulfillment and the rejection in the same then call using 2 separate handlers:
function foo(cb) {
Q.fcall(function () {
return true;
}).then(function (result) {
return cb(null, result);
}, function (err) {
return cb(err, null);
});
}