首页 > 解决方案 > 当我尝试在 Visual Studio Code 的终端中使用 Node.js 时,我收到“文档未定义”错误消息

问题描述

我是编程新手,目前正在研究 MySQL 数据库。我正在为我的所有 JavaScript、HTML 和 CSS 文件使用 Visual Studio Code。

我有一个给我问题的 JavaScript 服务器文件。我们的教授向我们提供了他的服务器 JavaScript 文件(发布在下面)、他的客户端 JavaScript 文件(名为contacts.js)和他的 HTML 文件的代码。

他告诉我们打开服务器 JavaScript 文件,打开终端并输入:node contacts.js。但是,这样做会给我错误消息,指出文档未定义。

在此处输入图像描述

有时,我什至会收到“找不到模块”错误。

上周我们刚刚做了一个类似的项目,终端使用类似的 node.js 命令运行良好,但我现在遇到了问题,不知道该怎么做。Google 上的几个小时根本没有帮助,整个星期都无法联系到我的教授。

我不确定如何解决这个“未定义文档”错误。任何帮助,将不胜感激。

下面是服务器 JavaScript 文件:

// The following statements are for database connection and queries
var mysql = require('mysql');                               // use the msql libraries. Must use 'npm install msyql --save' before using
var bodyParser = require('body-parser');                    // use the body-parser library for JSON use. Must 'npm install body-parser --save'
// Set up the SQL connection to the MYSQL database. This will all need to match what you set up in your DB
var connection = mysql.createConnection({           
    host:'localhost',
    user: 'mike',
    password: '********',
    database: 'contacts'
});
// do the actual connecting by calling the connect method and log the result
connection.connect();
console.log("After connection to DB established in server, setting up web server");

//The following are for web server setup - we are using the express library that makes this all pretty easy
const express = require('express');                         // use express library. must use 'npm install express --save'
const cors = require('cors');                               // use cors library. must use 'npm install cors --save'
const app = express();                                      // get the express application object
const path = require('path');                               // use the path library for managing paths. must use 'npm install path --save'
const port = 3000;                                          // constant for the port we're using. 
// set up the use of JSON url-encoding. Allows us to put all the arguments in the url
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

// We want to also serve static pages. This command sets that up. In my case, I created a subdirectory called 'public'
//  and put the main html page (contacts.html), the javascript client file (contacts.js) and the CSS file (contacts.css)
//  in that directory, and therefore I can get everything I need by just goint to (localhost:3000) and it all just works
app.use(express.static('public'));

// This is our main save handler (express calls these 'middleware'). The request coming from the client is a post
//  and all the parameters/values are in the query object in the request object (req).
//  All the field names here must match the names in the form (name='blah') which we use when we craft the request
//  in the javascript saveContact().
// NOTE: we have to use the cors() method to make this all work. Look up cors (Cross-Origin Resource Sharing) to learn about it
app.post('/save', cors(), function (req, res) {
    console.log("trying to save contact (post)");           // Log what we're doing
    console.log(req);                                       // log the actual request
    var curId = req.query.Id;                               // Get the Id from the query object
    var firstName = req.query.fname;                        // get the fname from the query object
    var lastName = req.query.lname;                         // get the lname from the query object
    var age = req.query.age;                                // etc. etc. etc.
    var phone = req.query.phone;
    var email = req.query.email;
// We can use the same handler for both cases of saving information:
//   1)we INSERT the new contact in the DB - the Id is 0 in this case
//   2)we UPDATE an existing contact in the DB - the Id is the correct Id for the contact we're updating
//  Here we're crafting the appropriate SQL statements using the values above - either INSERT or UPDATE
    if (curId > 0) {
        var sql = `UPDATE contacts SET fname = '${firstName}', lname = '${lastName}', age = ${age}, phone = '${phone}', email = '${email}' WHERE Id = ${curId}`;
    } else {
        var sql = `INSERT INTO contacts (fname, lname, age, phone, email) VALUES ('${firstName}', '${lastName}', '${age}', '${phone}', '${email}')`;
    }
// Here we're creating the query and the callback function for when we get a response from the DB asynchronously
//  This same method executes the SQL call to the database connection we established earlier (above)
    connection.query(sql, function (err, result) {
        console.log("Trying to save contact into DB");      // log what we're doing
        if (err) throw err;                                 // If we get an error, send the error along
        console.log(result.affectedRows + " record(s) saved");    
        res.status(201).send(result);                       // set the status code (201 = successful add) and send it
        console.log(`result of post is: ${result}`);        // log the result
        console.log(result);
    });
});

// This handler is for deleting a user given a valid Id.
// NOTE: we have to use the cors() method to make this all work. Look up cors (Cross-Origin Resource Sharing) to learn about it
app.post('/delete', cors(), function (req, res) {
    console.log("trying to delete contact (post)");         // log what we're doing
    console.log(req);                                       // log the actual request we received
    var curId = req.query.Id;                               // get the Id from the query object
    console.log(curId);                                     // log the Id
// As long as we have a valid Id (in variable curId), we craft the sql statement and execute the query
//  all the SQL commands are asynchronous so we provide a callback function
    if (curId > 0) {
        var sql = `DELETE FROM contacts WHERE Id = ${curId}`;   // This is the right SQL statement 
        connection.query(sql, function (err, result) {
            console.log("Trying to delete contact from DB");    // log what we're trying to do
            if (err) throw err;                                 // if we get an error, pass it along to the client
            console.log(result.affectedRows + " record(s) deleted");    
            res.status(200).send(result);                   // otherwise set the status to success (200) and send the result to the client
            console.log(`result of post is:`);    // log the result
            console.log(result);
        });
    }
});

// THis is our static GET Handler if you just open a browser and type in 'http://localhost:3000'. the '/' means root
//  and so this our default page (often called 'index.html' but in this case it's our 'contacts.html')
//  Simply send the contacts.html page by getting the default path (wherever we have this javascript file) 
app.get('/', function (req, res) {
    console.log(req.params);
    res.sendFile(path.join(__dirname + '\\contacts.html'));
});

// This is our handler for getting the full list of contacts
// NOTE: we have to use the cors() method to make this all work. Look up cors (Cross-Origin Resource Sharing) to learn about it
app.get('/list', cors(), function (req, res) {
    console.log(`inside list GET function, req object is ${req}`);
    console.log(req);
// Craft the simple select statement that just gets everything in the contacts table
    var sql = `SELECT * FROM contacts`;
//Create the query and execute it, sending the appropriate result back to the client
    connection.query(sql, function (err, result) {
        console.log(`Trying to get list from DB - result is ${result}`);
        console.log(`Inside get list - result first row is ${result[0]}`);
        if (err) throw err;                                     // if we get an error, pass it along to the client
        res.send(result);                                       // simply send the result of the query to the client.
        console.log(`result of GET to list is: ${result}`);
    });
}); 

// This is what actually starts the express server, listening on the port constant we defined at the beginning
//  of the file (in this case I'm using 3000) and logging what we're doing.

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

下面是客户端 JavaScript 文件:

// This JavaScript file is in support of the contacts application. 
//  Users can see and manage all their contacts, where a contact is [Id, firstname, lastname, age, phone, email]
//  There are functions to manage the http interactions with the server backend
//  and to manage the screen/user experience

// This is a globally available array of contacts we get back from the server. Set it initially to an empty array
document.contactList = [];

// This is the function queries the server (using an HTTP GET) to get the list of contacts
//  We save the contacts to a globable variable in the document (contactList) and we fill 
//  both the table at the bottom of the document and a drop-down list used for management
//    both of those functionality are function calls ('fillContactTable()' and 'fillContactSelect()')
function getContacts() {
    console.log(`Getting contact list from server`);                // log what we're doing
    var xhttp = new XMLHttpRequest();                               // create a variable for HTTP protocol
    xhttp.onreadystatechange = function() {                         // callback function for when a response occurs
        console.log(this.responseText);                             // log the response
// readyState is the XMLHttpRequest state that means we're done. Status is what is returned from the server
//   a status code anywhere in the 200's is success. SO if we're done and get a success return code, then we're good!
        if (this.readyState == 4 && (this.status >= 200 && this.status < 300)) {
            console.log(`Got the contact list successfully`);       // Log that we're good
            document.contactList = this.responseText;               // The response is the actual list of contacts.Set to globabl var in document
            fillContactTable();                                     // Fill the table
            fillContactSelect();                                    // Fill the drop down list (select element)
        } else {
            console.log(`failed to get contact list`);              // Log failure if that's what we got
        }
    }
// We've set the callback function that handles the result. This is the actual setting up the http request (the open method)
//   and the actual sending of the http request (send method)
    xhttp.open("GET", "http://localhost:3000/list", true);
    xhttp.send();
}

// Given an Id of a contact, get the rest of the contact information and return it
//  The pLocal parater is in case we want to get the contact information from the server instead of getting it from 
//   the global variable (document.contactList). Default is to be local.
function getContactById(pId, pLocal = true) {
    console.log(`Getting contact by ID = ${pId}`);                  // log what we're doing
    if (pLocal) {                                                   // If we're local, get the data from document.contactList
        var contactsJSON = JSON.parse(document.contactList);        // parse the contactList into JSON format - easier to deal with
// Loop through all the contacts in the JSON formated list of contacts to look for the one we want (by Id)
        for (loopIndex = 0; loopIndex < contactsJSON.length; loopIndex++) {
            if (contactsJSON[loopIndex].Id == pId) {                // if Id's match, we're good but log what we found
                console.log(`Found contact in getContactById. Index = ${loopIndex}`);
                console.log(contactsJSON[loopIndex]);
                return contactsJSON[loopIndex];                     // Return the found contact
            }
        }
        console.log(`Did not find the contact in getContactById`);  // log the fact that we didn't find it and return null
        return null;
// For now, if we're not local just return null. Will add the code to get the data from the server later
    } else {
        return null;
    }
}

// Simple function that just clears the form that we use for showing, creating new, and updating contacts
function clearEditForm() {
    console.log("clearing the contact form");                       // Log what we're doing
// Set all the values to empty (or 0 for the Id - that has to be a number)
    document.getElementById('contact_id').value = 0;                
    document.getElementById('contact_fname').value = "";
    document.getElementById('contact_lname').value = "";
    document.getElementById('contact_age').value = "";
    document.getElementById('contact_phone').value = "";
    document.getElementById('contact_email').value = "";
// Now control the user experience. Hide the ID fields and change the name of the button to "Insert"
    document.getElementById('contact_id').hidden = true;
    document.getElementById('contact_id_label').hidden = true;
    document.getElementById('save_button').innerHTML = "Insert Contact";
    document.getElementById('save_button').name = "Insert Contact";
}

// Main function that saves the contact form. We have two cases to deal with:
//   1) We're inserting a new contact. In that case, the Id (curId below) will be 0
//   2) We're updating an exesting contact. In that case, the Id will NOT be 0
// If the ID is not a number >= 0, we have a problem so we don't do anything
function saveContact() {
    console.log("Attempting to save contact");                      // Log what we're doing
// Get all the values from the elements in the form by name. 
    var curId = document.getElementById('contact_id').value;
    var curFName = document.getElementById('contact_fname').value;
    var curLName = document.getElementById('contact_lname').value;
    var curAge = document.getElementById('contact_age').value;
    var curPhone = document.getElementById('contact_phone').value;
    var curEmail = document.getElementById('contact_email').value;
    console.log(`Trying to save contact in saveContact. Id = ${curId}`);
// As long as we have a valid Id (number at least 0) we'll make the http request (a POST)
    if (curId >= 0) {
        var xhttp = new XMLHttpRequest();                           // Create a new HTTP object and put it in xHTTP variable
// As in all of our interactions implementing http, we supply a callback function for when we actually get a response
//  Remember, all http request/responses should be asynchronous, and so we have to use callbacks
        xhttp.onreadystatechange = function() {                     
            console.log(this.responseText);                         // log what's happening
// If readyState shows we're done (value == 4) and status code is in the 200's we got a success response
            if (this.readyState == 4 && (this.status >= 200 && this.status < 300)) {
                console.log(`saved the contact successfully`);      // Log our success
                getContacts();                                      // Re-get our contact list since it has changed
            } else {
                console.log(`failed to save contact `);             // Log our failure response
                console.log(this.status);                           // log the actual status code
                console.log(this.responseText);                     // log the actual response text
            }
        }
// Here we're crafting the http POST request with all the parameters urlencoded. Look up url encoding to understand it
//  As usual, the open method is used to set up the call, and the send method actually sends the request
        xhttp.open("POST", `http://localhost:3000/save?Id=${curId}&fname=${curFName}&lname=${curLName}&age=${curAge}&phone=${curPhone}&email=${curEmail}`, true);
        xhttp.send();
    }
}

// Function to delete a contact by creating the right server http request (a POST)
//  We'll pass the Id of the contact we want to delete in the url (url-encoded)
// We'll get the name of the contact to be deleted and prompt the user to verify that they want to really delete the contact
//  look up the window method 'confirm' to understand how that works
function deleteContact() {
    console.log("Attempting to delete contact");                    // Log what we're doing
    var contactList = document.getElementById('contacts_list');     // get the drop-down select element in the form
    var curId = contactList.value;                                  // get the value of the form, which will be an Id of the contact to be deleted
    var curIndex = contactList.selectedIndex;                       // We need the index of the option chosen to get the name for prompting the user
    var curName = contactList.options[curIndex].text;               // get the name from the option list based on the index
    console.log(`Trying to verify delete. curid = ${curId}, curIndex = ${curIndex}, and curName = ${curName}`);
// Prompt the user to confirm using the window.confirm method. If they say ok, confirm returns true
//  if they say cancel, confirm returns false. We're checking for the false, thus the not (!) at the beginning of the condition
    if (!confirm(`Are you sure you want to delete contact: ${curName}?`)) {
        return;                                                     // If we're here they said cancel, so just return out of here
    }
    console.log(`Trying to delete contact in fillEditForm. Id = ${curId}`);
    if (curId.length > 0) {                                         // Make sure we have a good Id
        var xhttp = new XMLHttpRequest();                           // create the http object
// Here's our callback for the asynchronous return. As long as we get a good status code, we update the form appropriately
        xhttp.onreadystatechange = function() {                 
            console.log(this.responseText);                         // log the actual response
// readyState 4 means we're done, and status in the 200's means success, so re-get the contact list from the server
            if (this.readyState == 4 && (this.status >= 200 && this.status < 300))  {
                console.log(`deleted the contact successfully`);
                clearEditForm();                                    // clear the form since we deleted the contact
                getContacts();                                      // get the contacts from the server
            } else {
                console.log(`failed to delete contact list`);
            }
        }
// Create the actual request and send it. 
        xhttp.open("POST", `http://localhost:3000/delete?Id=${curId}`, true);
        xhttp.send();
    }
}

// Simple function to clear the table element. We delete all the rows backwards. Make the function generic by allowing 
//  a parameter (pTable) which is the name of the table to be reset if there is more than one on the form
function tableDeleteRows(pTable = "") {
    var curTable;
    if (pTable.length == 0) {
        curTable = document.getElementById('contacts_table');
    } else {
        curTable = document.getElementById(pTable);
    }
// We start at the end of the rows (rows[length-1]), deleting backwards until we delete all of them
    for (i = curTable.rows.length - 1; i >= 0; i--) {
        curTable.deleteRow(i);
    }
}

// Simple function to clear a drop-down select element. We delete all the rows backwards. Make the function generic by allowing 
//  a parameter (pSelect) which is the name of the select element to be reset if there is more than one on the form
function selectDeleteOptions(pSelect = "") {
    var curSelect;
    if (pSelect.length == 0) {
        curSelect = document.getElementById('contacts_list');
    } else {
        curSelect = document.getElementById(pSelect);
    }
// Go backward from the end of the list of options in the select, removing them until we remove all of them
    for (i = curSelect.length - 1; i >= 0; i--) {
        curSelect.remove(i);
    }
}

// Assuming we have a contact chosen in the drop-down select element, fill the edit form with all the values for that contact
function fillEditForm() {
    console.log("filling the contact form");                            // Log what we're doing
    var contactList = document.getElementById('contacts_list');         // get the drop-down list
    var curId = contactList.value;                                      // the selected element Id is the value of the list
    console.log(`Trying to find contact in fillEditForm. Id = ${curId}`);
    var curContact = getContactById(curId);                             // Get the whole contact by calling the function
    console.log(curContact);                                            // log the contact we're using to fill the form
// As long as we have a good contact, we fill the form
    if (curContact != null) {                                       
        document.getElementById('contact_id').value = curContact['Id'];
        document.getElementById('contact_fname').value = curContact['fname'];
        document.getElementById('contact_lname').value = curContact['lname'];
        document.getElementById('contact_age').value = curContact['age'];
        document.getElementById('contact_phone').value = curContact['phone'];
        document.getElementById('contact_email').value = curContact['email'];
    }
// after we fill the form, we set elements appropriate to things like update and delete instead of add new
    document.getElementById('contact_id').hidden = false;
    document.getElementById('contact_id').disabled = true;
    document.getElementById('contact_id_label').hidden = false;
    document.getElementById('save_button').innerHTML = "Update Contact";
    document.getElementById('save_button').name = "Update Contact";
}

// This function fills the table at the bottom of the document with all the contacts and all the information
function fillContactTable() {
    console.log("Filling the contacts table in the form");              // Log what we're doing
    tableDeleteRows("contacts_table");                                  // Reset the table
// if we don't have anything in the global contact list - forget it and return
    if (document.contactList.length == 0) {
        console.log("the contact list/array is empty!");
        return;
    }
// We have contacts in the global array, so first parse the array into JSON and process it
    var contactsJSON = JSON.parse(document.contactList);
    var properties = ['Id', 'fname', 'lname', 'age', 'phone', 'email'];     // we need the property names
    var tr, curRow;                                                         // variables for table properties
    var contactTable = document.getElementById("contacts_table");           // get the table element
// cycle through the rows in the contacts array
    for (var rowIndex = 0; rowIndex < contactsJSON.length; rowIndex++) {    
        console.log(`Creating table rows, rowindex is ${rowIndex}`);
        tr = document.createElement('tr');                                  //create a new table row element
        curRow = contactsJSON[rowIndex];                                    // get the current row from the array
        console.log(curRow);                                                // log the data in the current row
// Cycle through the columns - defined in the property array above and add column elements to the row in the table
        for (var i = 0; i < properties.length; i++) {                       
            console.log(`Creating table columns for row ${i}, property is ${properties[i]} value is ${curRow[properties[i]]}`);
            var td = document.createElement('td');                          // create a data element for the column
            td.appendChild(document.createTextNode(curRow[properties[i]])); //Append the property data to the new data element
            tr.appendChild(td);                                             // append the new data element to the row element
        }
        contactTable.appendChild(tr);                                       // append the row element to the table element
    }
    console.log("Finished procesing contacts list");    
}

// Fill the drop-down select. First reset the select (removing all options), then recreate it
function fillContactSelect() {
    console.log("Filling the contacts drop down select in the form");       // log what we're doing
    selectDeleteOptions("contacts_list");                                   // Reset the select element clearing all options
// if we don't have anything in the global contact list - forget it and return
    if (document.contactList.length == 0) {
        console.log("the contact list/array is empty!");
        return;
    }
// We have contacts in the global array, so first parse the array into JSON and process it
    var contactsJSON = JSON.parse(document.contactList);
    var properties = ['Id', 'fname', 'lname'];                              // only need Id, fname, lname for drop down
    var option, curRow;                                                     // variables for table properties
    var contact = document.getElementById("contacts_list");                  // get the select drop down element
// cycle through the rows in the contacts array
    for (var rowIndex = 0; rowIndex < contactsJSON.length; rowIndex++) {    
        console.log(`Creating select items, rowindex is ${rowIndex}`);
        option = document.createElement('option');                          //create a select option element
        curRow = contactsJSON[rowIndex];                                    // get the current row from the array
        console.log(curRow);                                                // log the data in the current row
// the value of this option will be the id, since that's what we'll use to get a contact. The text is fname + lname
        option.value = curRow["Id"];
        option.appendChild(document.createTextNode(`${curRow['fname']} ${curRow['lname']}`));
        contact.appendChild(option);                                        // append the option to the select element
    }
    console.log("Finished procesing contacts list");    
}

// When the windo first loads, get the list of contacts which will also fill the table and drop down list
window.onload = function() {
    getContacts();
};

标签: javascriptnode.jsvisual-studio-code

解决方案


您正在运行错误的 JS 文件。你想做:

node contactserver.js

目前您正在运行contacts.js,这是客户端代码。

为了对此进行扩展,您会看到该错误,因为 document 是浏览器中可用的全局变量,但在 Node.js 中不可用。设计用于在浏览器中运行的前端代码通常依赖于服务器上根本不存在的浏览器 API,因此尝试在服务器环境中运行仅客户端文件时会在找不到全局对象时抛出错误存在于浏览器中。

向@Jon Church 提供以下评论中的解释的道具


推荐阅读