My question is if is it possible to achieve the following implementation in NodeJS without using any callback or asnyc/await or promises or synchrounous libraries in the caller file?
Caller File:
const isUnique = require("is-unique");
if(!isUnique({email:req.user.email})){
//call is-unique to check if unique, if not unique return 400
return res.status(400).json({"error":"Profile exist"})
}
Callee File:
// is-unique.js
const isUnique = (field) => {
//call an async function countRecordsInDatabase, check the result and return a boolean
const count = countRecordsInDatabaseAsync(field);
return (count <= 0);
}
module.exports = isUnique;
Thanks in advance and hope I have made the question short and sweet. :D
You want to call an async function, in a sync function and not have the sync function be async. It seems like that is what you are asking.
There are libraries that suggest they can do this, however it doesn't sound like a great idea.
What are you trying to achieve?
I'll keep it real with you. If most people aren't doing things this way, which they aren't it's prolly not a good idea to do it differently.
Related
I'm struggling with callbacks in Node.js. I simply want playerNumber to be set to the number of players in my collection of Players. The console.log works, but I can't get the variable out of the function and into the playerNumber variable.
And if there's a simpler way get this value for use in the rest of my backend code, I'm all ears. I'm clearly new at Node.js, but the code always seems more involved than I'm expecting.
Thanks in advance!
var playerNumber = function countPlayers(callback){
Player.count(function(err, numOfDocs) {
console.log('I have '+numOfDocs+' documents in my collection');
callback(err, numOfDocs);
});
}
It's probably async, and it's a typical first-timer experience to want to "get back to normal" on the call chain on the way back from async call. This can't be done, but it's not so bad to live with it. Here's how...
Step 1: Promises are better than callbacks. I'll leave the long story
to others.
Step 2: Callbacks can be made into promises
In the OP case...
// The promise constructor takes a function that has two functions as params
// one to call on success, and one to call on error. Instead of a callback
// call the 'resolve' param with the data and the 'reject' param with any error
// mark the function 'async' so callers know it can be 'await'-ed
const playerNumber = async function countPlayers() {
return new Promise((resolve, reject) => {
Player.count(function(err, numOfDocs) {
err ? reject(err) : resolve(numOfDocs);
});
});
}
Step 3: Yes, the callers must deal with this, and the callers of the callers, and so on. It's not so bad.
In the OP case (in the most modern syntax)...
// this has to be async because it 'awaits' the first function
// think of await as stopping serial execution until the async function finishes
// (it's not that at all, but that's an okay starting simplification)
async function printPlayerCount() {
const count = await playerNumber();
console.log(count);
}
// as long as we're calling something async (something that must be awaited)
// we mark the function as async
async function printPlayerCountAndPrintSomethingElse() {
await printPlayerCount();
console.log('do something else');
}
Step 4: Enjoy it, and do some further study. It's actually great that we can do such a complex thing so simply. Here's good reading to start with: MDN on Promises.
I am new to async functions. I want to utilize the code below to ask the user a question and react to the question with an X or check mark to get the users answer on whether or not to delete something to make room for a new entry.
The function below works perfectly fine. However, I want to pass the result from the function out of the function so I can make an if else statement outside of it and that is where I am stuck.
I've looked around online and saw several things related to callbacks being used, but each example I've seen is different for something I think is similar, so I am just confused. And none of these examples have been used for Reactions on Discord, so I'm just not sure where to go.
const agree = "✅"
const disagree = "❌"
let msg = await message.author.send("You have made the maximum number of decks. Would you like to delete one of your decks in order to make a new one? Please react with one of the following...")
await msg.react(agree)
await msg.react(disagree)
const filter = (reaction, user) => {
return ['✅', '❌'].includes(reaction.emoji.name) && user.id === message.author.id;
};
const reactions = await msg.awaitReactions(filter, {
max: 1
}).then(collected => {
const result = collected.last();
})
return result;
}
deleteDeckQuestion(function(result){
console.log(result)
}).catch(err => console.error(err))
The above code results in 'undefined' being logged to the console when I run deleteDeckQuestion. No errors otherwise. I would like it to make the Results variable accessible to me outside the function so I can make an if else statement based upon which reaction the user added to the question.
I tried putting the if else statement I wanted to use with the results of deleteDeckQuestion inside the async function and it operated fine, but then inside the "Yes" result of that function, I want to put another Async function to ask which deck 1, 2 or 3 should be deleted and have the same reaction-determines-answer-to-question scenario. Just saves the user typing more than necessary at the ease of mobile users.
Would it be easier I just put an async function inside another async function? Something tells me that isn't the best idea in terms of efficiency. Eventually these reactions will lead to using mysql queries, which I am comfortable with using, but it will get pretty lengthy and functions inside other functions just seems like a mess... not sure if that is part of the "callback hell" I've read the joys of though...
Thanks for any help in advance.
collected within your then() callback and reactions are the exact same object. However, result's scope is limited to within the callback.
In this example code, collected is the result of msg.awaitReactions(...)'s fulfilled promise. Then, result is declared in the same scope, and therefore accessible where you need it to be.
const collected = await msg.awaitReactions(filter, { max: 1 })
.catch(console.error);
const result = collected.first();
MDN: Async Programming, await, then(), scope
Discord.js: Message.awaitReactions()
Is it possible to use await inside a normal function?
For Example:
function myFunction(v1, v2) {
let v3 = await some db operation; returns a array
console.log(v3);
//do something
};
Yes, all async code is called from a normal function somewhere, but no you can't use the await keyword in a non-async function.
Async functions look like promises when inside non-async functions.
function myOuterFunction(v1, v2) {
myFunction(v1, v2)
.then(console.log)
.catch(console.error);
}
async function myFunction(v1, v2) {
let v3 = await some db operation; returns an array
console.log(v3);
//do something
};
(This example uses the functions console.log and console.error to handle returned values and exceptions.)
No, and for a good reason.
Before async functions were introduced: the following was entirely possible:
function foo() {
var await = 42;
var result = await + 42;
}
If they had made it so await was available in normal functions, that code would have been retroactively broken, causing what's called a backwards compatibility break.
This is also why yield is only available within function*.
No. The "magic" of asynchronous programming – that, in JavaScript, includes the usage of await – is that it doesn't block the execution of other code. If you want to use it, you have to adapt your codebase to use async functions where it makes sense.
If you really need to wait for asynchronous actions to complete inside normal synchronous functions, you could check whether the library you're using also offers sync functions (fs-extra for example does). But please, unless there's a really good reason not to, make your code asynchronous.
I'm unable to get the values in meals object although i have create new object at the top can any one tell which is the best procedure access variable inside callback function
var meals = new Object();
passObj.data = _.map(passObj.data, (x)=> {
x.mealImageUrl = !_.isNull(x.image_url) ? `${config.image_path}${x.image_url}` : x.image;
dbHelpder.query(`select * from meals where meal_category = ${x.category_id}`,(error,result)=>{
meals = x.result;
passObj.total = 555
});
return x;
});
You need to use callback again inside the callback function. :)
You are doing something asynchronous, it means, there are no sequence codes. (At least, I keep this in my mind, don't know how others think about this.) So, the code should be:
function somehow(callback) { // you get the result from callback
var meals = new Object();
passObj.data = _.map(passObj.data, (x)=> {
dbHelpder.query(`select * from meals where meal_category = ${x.category_id}`,(error,result)=>{
meals = x.result;
passObj.total = 555;
callback(meals); // Here you get the result
});
}
return x;
}
So, when you are going to use this function, it should be
function afterMeals(resultMeals) {
// do something on the meals
}
somehow(afterMeals);
Use some other technology can make it a bit clear (like promise), but you can not avoid callback actually.
First of all, I cannot see what passObj exactly is, apparently it is defined elsewhere.
Secondly, callback functions don't function the way you seem to think they do. Typically one reason to use them is to implement asynchronous calls, so returning a value is not of use.
The idea is as follows. Usually you have a call like this:
var myFunc1 = function(){
return 42;
}
var x = myFunc1();
myFunc2(x);
However when myFunc1 is an asynchronous call returning a value is impossible without using some sort of promise, which is a topic on its own. So if myFunc1 was an asynchronous call and the 42 was returned e.g. by a server, then just returning a value caused the value to be null, because the return value is not calculated and received yet, when you arrive at return.
This is a reason for callbacks to be introduced. They work in a way, that allows for asynchronous calls and proceeding the way you want to after the call has finished. To show on the example above:
var myFunc1 = function( myFunc2, params ){
// do async stuff here, then call the callback function from myFunc1
...
myFunc2(x);
}
So the asynchronous function doesn't return anything. It makes the calls or calculations it needs to make and when those are done (in the example that is when x has been declared and assigned a value) myFunc2, which is the callback function in our example, is called directly from the asynchronous function.
Long story short - do what you need to do with x directly inside the callback function.
I know out of the box Q won't support this, but I'm wondering if it is theoretically possible to do something like this:
var user = Q.spawn(function* () {
var createdUser = yield createUser();
return user;
});
console.log(user); // user is available here
I may be wrong, but I would say yes, it is possible theoretically, it's just not intended to work like that. That's why Q doesn't support it.
I'm not sure why Q.done doesn't invalidate the promise chain altogether, preventing further calls to p.then to succeed (maybe it's impossible), but right now (Q is at version 1.2.0 at the time of this writing) it doesn't:
var p = Q("Test");
p.done();
p.then(function(message) {
console.log(message); // "Test" is logged here just fine.
});
// No runtime errors.
So Q.spawn needed only return the result of Q.async(generator)() after calling Q.done on it to support that, like this:
Q.spawn = spawn;
function spawn(makeGenerator) {
var p = Q.async(makeGenerator)();
Q.done(p);
return p;
}
That said, it seems clear to me that the API doesn't want to encourage using a done promise chain: Contrary to Q.then and Q.catch, for example, neither Q.done nor Q.spawn return any promise for chaining.
The library authors were either not sure if this was a good idea (and so didn't want to encourage it, but didn't also implement something that prohibits done promises from being used) or were outright convinced it's not.