2

I don't understand callbacks in nodejs.

I need to get a podcast number from the database and use it in my code

I get right now from console.log

[Function: index]

Is there any solution in node.js to get variable from a database and reuse it later in the code?

var index = function( callback ) {   
    var podcast = 0;  
    User.findOne({ sessionID: this.event.session.sessionId }, function(err, user) {
          if (err ||!user){

          }
          else {
             console.log(user);
             podcast = user.podcast;
          }
        });
    callback( podcast );
};

index();

var callback = function(data) {
    return data;
}

var iUseMyAnywhere = callback;
Anna K
  • 1,666
  • 4
  • 23
  • 47
  • @dm03514.thanks I asked you to not close it instantly. Are you proud of you?`Happy`? – Anna K Oct 26 '17 at 11:50
  • @AnnaK the short answer is no. A callback runs at some point in the future that you can’t predict, so things that happen inside it’s block are only available in that block. If you want behavior more like you’re used to, you’ll need to use Promises along with the new async/await feature in the recent Node versions. – Paul Oct 26 '17 at 11:59
  • @Paul thank you :) Could you recomend me please any link? Is it hard to implement to my case? – Anna K Oct 26 '17 at 12:00
  • Looks like I can't answer, but here's the docs. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function – Paul Oct 26 '17 at 15:20

2 Answers2

2

It look like it is impossible what I want to do in Node.js

It's completely possible. Only, you need to use asynchronous API's, which makes it ankward.

Is there any solution in node.js to get variable from a database and reuse it later in the code?

Not exactly. When you connect to a database -or, by the way, do anything asynchronously, like fetching something over http or reading from disc- you can't assign that thing right over:

var myUserFromDb = User.find('john doe', function(err, res){...}); //this will fail 

Because that function you're passing as the second parameter will execute sometime in the future. User.find() itself doesn't return the user.

So, sadly, you can't just get the user in the user var and pass it to another module -let's say a podcast module-.

However, let's say you have a 'user.js' module, with exposes a withUser method than aks the database for a user and then calls a provided function with the user, when the db call is resolved.

And let's say you have a 'podcast.js' file/module with a getPodcast method that needs a user.

getPodcast can't just ask 'user.js' a user. However, it can ask for a function that will run with the user passed as parameter:

User.js

function withUser(callback){
    User.find({_id: 1}, (err, user)=> {
        callback(user);
    })
}

podcast.js

function getPodcast(){

    withUser( function(user){
        //now we really have the user inside podcast.js, and we can work with it.
        //Sadly, that will surely involve more asynchronous api's, which is painful.
    })
}

Now getPodcast will have access to the user inside its parameter callback.

Is there any easier method rather than callback?

Yes, you should read about promises. When using promises, things are -a little less- painful. A promise api would work as:

User.js

function getUser(id){
    //let's say we return a promise that wraps the `User.find` database request
}

podcast.js

getUser(userId).then(user => getPodcast(user)).then(podcastResult => ...)

This don't see really better. However, when you are working with promise api's, you can then start using async/await.

podcast.js

 async function getPodcast(userId){
      const user = await User.getUser(uesrId);
      const otherAsyncThing = await ...someAsyncApiCall;

      doAnythingWithUser(user); //this line won't execute until user is resolved, even if there aren't callbacks involved :-D
 }

A final, unasked word of advice: when working with node.js, be sure you understand how callback api's and async things really work before writing a ton of code. Otherwise, you'll get really coupled and brittled code, where objects get passed through mountains of callbacks and code is unreadable and undebuggable :-D

Sergeon
  • 6,638
  • 2
  • 23
  • 43
1

PS. Edited to follow question.

Think like this, you get to a restaurant, sit down and ask a waitress for a coffee. But in the meanwhile you are not frozen, you are moving, doing things, talking, so once your coffee is ready, the waitress will bring it to you and you will stop other things that you are doing and drink your coffee.

So, it would become something like this:

    User.findOne({ sessionID: this.event.session.sessionId }).exec().then(data => {
    console.log(data);
}).catch(err => {
    console.log(err);
});
Andy
  • 1,190
  • 1
  • 11
  • 25
  • It look like it is impossible what I want to do in Node.js :( What is router? Is it a nodejs module? As a good JS Developer could you advise me what would be the best to solve my problem. I just want to get data from a database and put it to another variable which is userd later in my code – Anna K Oct 26 '17 at 12:54
  • Thank you for your help but I still can not solve my problem :( Im crying again – Anna K Oct 26 '17 at 12:59
  • You need to create another function called callback to consume your data else where in the code. See my edit. – Andy Oct 26 '17 at 13:00
  • Andy but I dont want to put this variable into the console I wish to pass it to another variable for example podcasts. I wish to use podcasts as a value from my database in another places. I updated my question. You are my hero today :) – Anna K Oct 26 '17 at 13:03
  • All what you have to do is use return whenever you need to use the data. Assign callback to a variable like in the example. But for the looks, you are moving to fast before grasping other key concepts. You need to get other aspects of Coding before moving to callbacks. It is a pain in the backpack for a lot people, that is a reason people call it callback hell. I personally hate it. I use observables to deal with them and sometimes promises. But – Andy Oct 26 '17 at 13:11
  • Im getting that error if I try to use your last code TypeError: callback is not a function – Anna K Oct 26 '17 at 13:11
  • try removing callback from `index(callback)` instead `index()` Like I said, I rarely use callbacks bare like this. – Andy Oct 26 '17 at 13:15
  • the problem is here: callback( podcast );Unexpected exception 'TypeError: callback is not a function': TypeError: callback is not a function – Anna K Oct 26 '17 at 13:17
  • Did you add the callback function like in example above to your code? – Andy Oct 26 '17 at 13:20
  • I updated my question with your idea. I pasted it to me code. But it doesnt work – Anna K Oct 26 '17 at 13:22
  • Is there any easier method rather than callback? – Anna K Oct 26 '17 at 13:26
  • what error are you getting? Can you please share your code in github or else where so I can help you better by running it locally? – Andy Oct 26 '17 at 13:26
  • Andy, is there any way to solve my problem in JS? Something easy – Anna K Oct 26 '17 at 13:33
  • You could use promises, which is easier to understand than observables. But since you don't fully grasp callbacks, I'm not sure if you will be able to convert it to promises. If you share your code on github, I think I can help you better. – Andy Oct 26 '17 at 13:41
  • the problem is you wont be able to execute my code because Im writing it for amazon alexa :( Do you have any good tutorial for promises – Anna K Oct 26 '17 at 13:44
  • I see, I tried to convert to promises to help you out, I will post here a promise tutorial shortly so you can learn more. – Andy Oct 26 '17 at 13:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/157578/discussion-between-andy-and-anna-k). – Andy Oct 26 '17 at 14:10