简体   繁体   中英

Node.js, 'X' is not defined

I've been pulling my hair out with this one, trying to get my latest tweets as an array with https://github.com/noffle/latest-tweets npm module. however, no matter what way i seem to order it, i get some form of error. mainly posts is not defined or tweets is not defined.

 var express = require('express'); var latestTweets = require('latest-tweets') var Post = require('../models/blog'); var router = express.Router(); router.get('/', function (req, res) { Post.getPosts((err, posts) => { if(err){ throw err; } }); latestTweets('my_twitter_id', function (err, tweets) { console.log(tweets) }) res.render('index', {tweets : tweets, posts : posts}); }); 

I also tried to export the latestTweets function into a helper class which lead to more issues.

Both posts and tweets are variables from the callbacks. You can't use them outside the callback.

Quick fix:

router.get('/', function (req, res) {
    Post.getPosts((err, posts) => {
        if(err){ throw err; }

        latestTweets('my_twitter_id', function (err_, tweets) {
            if(err_){ throw err_; }
            console.log(tweets);

            res.render('index', {tweets : tweets, posts : posts});
        });
    });
});

Now, if you're looking for a prettier solution you can take a look at async module. async repo

You should take care of the scope of the variable while writing code. The posts and tweets variables are accessible only inside the callback functions in which they are passed as arguments, but you are accessing them outside their scope. Clearly, since the argument tweets is passed inside the callback of latestTweets , the variable tweets has a local scope limited to the callback. So, when the program reaches res.render , it tries to evaluate tweets and posts , and fails to identify them, and returns not defined .
Example

function myFunc(){
    var x = 0;
}
console.log(x);

The above function will return the same error x is not defined , since the outer code doesn't know what x is. It is local to the function myFunc , and is only accessible inside it. To make it accessible, you will have to make it global, ie, declare var x = 0 in the main code.
In your code, the best you can do is declare two variables inside the router.get function's callback (ie, global to the callback) and assign them to posts and tweets in their respective callbacks.

router.get('/', function (req, res) {
var tweets, posts;
Post.getPosts((err, posts) => {
    if(err){
        throw err;
    }
    posts = posts;
});
latestTweets('my_twitter_id', function (err, tweets) {
console.log(tweets)
tweets = tweets;
})
res.render('index', {tweets : tweets, posts : posts});

});

Using sessions is a better option than declaring variables while writing backend, because of a lot of reasons, which would be off-topic to explain here.

Also , avoid using nested callbacks. In this case, res.render might be called before the global variables tweets and posts are assigned a value, which will again throw an error signifying tweets and posts are undefined . In such cases, use Javascript's Promises which is the language's own feature to handle such requests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM