-->

What is this Javascript “require”?

2018-12-31 12:27发布

问题:

I\'m trying to get Javascript to read/write to a PostgreSQL database. I found this project on github. I was able to get the following sample code to run in node.

var pg = require(\'pg\'); //native libpq bindings = `var pg = require(\'pg\').native`
var conString = \"tcp://postgres:1234@localhost/postgres\";

var client = new pg.Client(conString);
client.connect();

//queries are queued and executed one after another once the connection becomes available
client.query(\"CREATE TEMP TABLE beatles(name varchar(10), height integer, birthday timestamptz)\");
client.query(\"INSERT INTO beatles(name, height, birthday) values($1, $2, $3)\", [\'Ringo\', 67, new Date(1945, 11, 2)]);
client.query(\"INSERT INTO beatles(name, height, birthday) values($1, $2, $3)\", [\'John\', 68, new Date(1944, 10, 13)]);

//queries can be executed either via text/parameter values passed as individual arguments
//or by passing an options object containing text, (optional) parameter values, and (optional) query name
client.query({
  name: \'insert beatle\',
  text: \"INSERT INTO beatles(name, height, birthday) values($1, $2, $3)\",
  values: [\'George\', 70, new Date(1946, 02, 14)]
});

//subsequent queries with the same name will be executed without re-parsing the query plan by postgres
client.query({
  name: \'insert beatle\',
  values: [\'Paul\', 63, new Date(1945, 04, 03)]
});
var query = client.query(\"SELECT * FROM beatles WHERE name = $1\", [\'John\']);

//can stream row results back 1 at a time
query.on(\'row\', function(row) {
  console.log(row);
  console.log(\"Beatle name: %s\", row.name); //Beatle name: John
  console.log(\"Beatle birth year: %d\", row.birthday.getYear()); //dates are returned as javascript dates
  console.log(\"Beatle height: %d\' %d\\\"\", Math.floor(row.height/12), row.height%12); //integers are returned as javascript ints
});

//fired after last row is emitted
query.on(\'end\', function() { 
  client.end();
});

Next I tried to make it run on a webpage, but nothing seemed to happen. I checked on the Javascript console and it just says \"require not defined.\"

So what is this \"require?\" Why does it work in node but not in a webpage?

Also, before I got it to work in node, I had to do npm install pg. What\'s that about? I looked in the directory and didn\'t find a file pg. Where did it put it, and how does Javascript find it?

回答1:

So what is this \"require?\"

require() is not part of the standard JavaScript API. But in Node.js, it\'s a built-in function with a special purpose: to load modules.

Modules are a way to split an application into separate files instead of having all of your application in one file. This concept is also present in other languages with minor differences in syntax and behavior, like C\'s include, PHP\'s use, Python\'s import, and so on.

One big difference between Node.js modules and browser JavaScript is how one script\'s code is accessed from another script\'s code.

  • In browser JavaScript, scripts are added via the <script> element. When they execute, they all have direct access to the global scope, a \"shared space\" among all scripts. Any script can freely define/modify/remove/call anything on the global scope.

  • In Node.js, each module has its own scope. A module cannot directly access things defined in another module unless it chooses to expose them. To expose things from a module, they must be assigned to exports or module.exports. For a module to access another module\'s exports or module.exports, it must use require().

In your code, var pg = require(\'pg\'); loads the pg module, a PostgreSQL client for Node.js. This allows your code to access functionality of the PostgreSQL client\'s APIs via the pg variable.

Why does it work in node but not in a webpage?

require(), module.exports and exports are APIs of a module system that is specific to Node.js. Browsers do not implement this module system.

Also, before I got it to work in node, I had to do npm install pg. What\'s that about?

NPM is a package repository service that hosts published JavaScript modules. npm install is a command that lets you download packages from their repository.

Where did it put it, and how does Javascript find it?

Node.js has very detailed documentation on how modules find other modules. But in a gist, it puts all the downloaded modules in node_modules in the directory where you ran npm install.



回答2:

Alright, so let\'s first start with making the distinction between Javascript in a web browser, and Javascript on a server (CommonJS and Node).

Javascript is a language traditionally confined to a web browser with a limited global context defined mostly by what came to be known as the Document Object Model (DOM) level 0 (the Netscape Navigator Javascript API).

Server-side Javascript eliminates that restriction and allows Javascript to call into various pieces of native code (like the Postgres library) and open sockets.

Now require() is a special function call defined as part of the CommonJS spec. In node, it resolves libraries and modules in the Node search path, now usually defined as node_modules in the same directory (or the directory of the invoked javascript file) or the system-wide search path.

To try to answer the rest of your question, we need to use a proxy between the code running in the the browser and the database server.

Since we are discussing Node and you are already familiar with how to run a query from there, it would make sense to use Node as that proxy.

As a simple example, we\'re going to make a URL that returns a few facts about a Beatle, given a name, as JSON.

/* your connection code */

var express = require(\'express\');
var app = express.createServer();
app.get(\'/beatles/:name\', function(req, res) {
    var name = req.params.name || \'\';
    name = name.replace(/[^a-zA_Z]/, \'\');
    if (!name.length) {
        res.send({});
    } else {
        var query = client.query(\'SELECT * FROM BEATLES WHERE name =\\\'\'+name+\'\\\' LIMIT 1\');
        var data = {};
        query.on(\'row\', function(row) {
            data = row;
            res.send(data);
        });
    };
});
app.listen(80, \'127.0.0.1\');


回答3:

It\'s used to load modules. Let\'s use a simple example.

In file circle_object.js:

var Circle = function (radius) {
    this.radius = radius
}
Circle.PI = 3.14

Circle.prototype = {
    area: function () {
        return Circle.PI * this.radius * this.radius;
    }
}

We can use this via require, like:

node> require(\'circle_object\')
{}
node> Circle
{ [Function] PI: 3.14 }
node> var c = new Circle(3)
{ radius: 3 }
node> c.area()

The require() method is used to load and cache JavaScript modules. So, if you want to load a local, relative JavaScript module into a Node.js application, you can simply use the require() method.

Example:

var yourModule = require( \"your_module_name\" ); //.js file extension is optional


回答4:

I noticed that whilst the other answers explained what require is and that it is used to load modules in Node they did not give a full reply on how to load node modules when working in the Browser.

It is quite simple to do. Install your module using npm as you describe, and the module itself will be located in a folder usually called node_modules.

Now the simplest way to load it into your app is to reference it from your html with a script tag which points at this directory. i.e if your node_modules directory is in the root of the project at the same level as your index.html you would write this in your index.html:

<script src=\"node_modules/ng\"></script>

That whole script will now be loaded into the page - so you can access its variables and methods directly.

There are other approaches which are more widely used in larger projects, such as a module loader like require.js. Of the two, I have not used Require myself, but I think it is considered by many people the way to go.



回答5:

You know how when you are running JavaScript in the browser, you have access to variables like \"window\" or Math? You do not have to declare these variables, they have been written for you to use whenever you want.

Well, when you are running a file in the Node.js environment, there is a variable that you can use. It is called \"module\" It is an object. It has a property called \"exports.\" And it works like this:

In a file that we will name example.js, you write:

example.js

module.exports = \"some code\";

Now, you want this string \"some code\" in another file.

We will name the other file otherFile.js

In this file, you write:

otherFile.js

let str = require(\'example.js\')

That require() statement goes to the file that you put inside of it, finds whatever data is stored on the module.exports property. The let str = ... part of your code means that whatever that require statement returns is stored to the str variable.

So, in this example, the end-result is that in otherFile.js you now have this:

let string = \"some code\";

Note:

the file-name that is written inside of the require statement: If it is a local file, it should be the file-path to example.js. Also, the .js extension is added by default, so I didn\'t have to write it.

You do something similar when requiring node.js libraries, such as Express. In the express.js file, there is an object named \'module\', with a property named \'exports\'.

So, it looks something like along these lines, under the hood (I am somewhat of a beginner so some of these details might not be exact, but it\'s to show the concept:

express.js

module.exports = function() {
    //It returns an object with all of the server methods
    return {
        listen: function(port){},
        get: function(route, function(req, res){}){}
     }
}