Я новичок в программировании и сейчас работаю над базой данных MySQL. Я использую код Visual Studio для всех моих файлов JavaScript, HTML и CSS.
У меня есть файл JavaScript server, который вызывает у меня проблемы. Наш профессор дал нам свой код для файла сервера JavaScript (который размещен ниже), его файл клиента JavaScript (который называется contact. js) и его файл HTML.
Он сказал нам, чтобы открыть файл сервера JavaScript, открыть терминал и набрать: контакты узла. 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();
};