8

is it easy/possible to run a node js file from another node js file? For instance, i'm having two files test1.js and test2.js. i want to execute the test1.js file from test2.js.

sudhakar
  • 582
  • 1
  • 3
  • 13
  • What do you mean by *execute*? How would it be different from doing `require('test2.js')` in test1.js? – adrianp Jul 12 '13 at 10:41
  • @adrianp "node test1.js" in this way we are executing or running the node js files. i want to run test1.js from test2.js – sudhakar Jul 12 '13 at 10:46
  • @sudhakar, are you talking about something [like this](http://www.dzone.com/snippets/execute-unix-command-nodejs)? – kentcdodds Jul 12 '13 at 10:48
  • @kentcdodds for instance, The contents of test1.js if (process.argv.length > 0) { var test_val = process.argv[1]; } console.log(test_val); if i run it in command "node test1.js wow" the output would be wow. so i want get output "wow" from test2.js – sudhakar Jul 12 '13 at 11:01
  • Do you merely want to run test1 separately or do you want to test1 to have access to test2 variables? – SheetJS Jul 12 '13 at 11:15

3 Answers3

15

I think the better way to accomplish what you're trying to do would be to do what my other answer suggests. But to execute commands on the command line as your questions suggests, you want to use child_process.exec. For example:

var exec = require('child_process').exec,
    child;

child = exec('node test2.js {{args}}',
  function (error, stdout, stderr) {
    console.log('stdout: ' + stdout);
    console.log('stderr: ' + stderr);
    if (error !== null) {
      console.log('exec error: ' + error);
    }
});
kentcdodds
  • 27,113
  • 32
  • 108
  • 187
12

You simply run require('test2.js'), and then call a function on the exported object. From the documentation on modules:

Node has a simple module loading system. In Node, files and modules are in one-to-one correspondence. As an example, foo.js loads the module circle.js in the same directory.

The contents of foo.js:

var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is ' + circle.area(4));

The contents of circle.js:

var PI = Math.PI;

exports.area = function (r) {
  return PI * r * r;
};

exports.circumference = function (r) {
  return 2 * PI * r;
};

The module circle.js has exported the functions area() and circumference(). To export an object, add to the special exports object.

Note that exports is a reference to module.exports making it suitable for augmentation only. If you are exporting a single item such as a constructor you will want to use module.exports directly instead.

function MyConstructor (opts) {
  //...
}

// BROKEN: Does not modify exports
exports = MyConstructor;

// exports the constructor properly
module.exports = MyConstructor;

Variables local to the module will be private. In this example the variable PI is private to circle.js.

The module system is implemented in the require("module") module.

Agamemnus
  • 1,395
  • 4
  • 17
  • 41
kentcdodds
  • 27,113
  • 32
  • 108
  • 187
  • 2
    Um... Not sure why this answer got a down vote. It's the correct way to interact with modules even if it's not the accepted answer... – kentcdodds Jul 12 '13 at 12:17
  • 4
    If I make it a module, I won't be able to run it alone. I have separate scripts for some tasks, and then some dispatcher script which can run all required tasks in specified order. If my tasks are as modules with exports, I cannot run those tasks alone, I'll have to create some wrapper script just to run a task. – JustAMartin Jul 16 '15 at 13:42
  • @J Simply wrap everything in a function and then test whether the script is running as a module or not: `// Allows us to run either directly or via another node.js script if (require.main === module) { // We are running directly runTest() } else { // We are a module in another script module.exports = runTest }` – Julian Knight Dec 05 '20 at 17:29
2

There are different scenarios here - using modules, loading them "the right way" - it's the way to go when writing your own code.

What about "random" .js files, e.g. downloaded via web scraping? (If this is a good idea to execute them is beyond the scope of this answer...)

Well - you can just require them, if you're only interested in the side effects:

test2.js:

console.log('hello')

test1.js:

console.log('about to execute')
require('./test2.js')
console.log('done')

Note the ./ in require(). But, if you want to run it twice, this won't work:

test3.js:

console.log('about to execute twice?')
require('./test2.js')
require('./test2.js')
console.log('surprise')

This shows, that require works like a Python import - only executing the file if it hasn't been loaded yet. But - it's possible to circumvent it and force a reload: How to remove module after "require" in node.js?

test4.js:

console.log('about to execute twice!')
require('./test2.js')
delete require.cache[require.resolve('./test2.js')]
require('./test2.js')
console.log('NO surprise this time around')

The difference from a Python import is that you can't import anything unless it's exported. So you would have to change the required file and do something with module.exports.

If you're working with the node shell, there is an alternative:

test5.js:

console.log('the const below is private?')
const x = 5

And then:

$ node
> .load test5.js
console.log('the const below is private?')
const x = 5

the const below is private?
undefined
> x
5

Note that there are no quotes around filename in .load, and also no ./. This is somewhat verbose when used (echoing the loaded script). But it is at least some way of playing with the values the script creates.

Final warning: always be careful about what you're about to execute!

Tomasz Gandor
  • 8,235
  • 2
  • 60
  • 55
  • "./" did what I was looking for (different from the original poster). I don't know enough about node.js yet, but I have a feeling that when you leave the path blank, it automatically defaults to looking in the node_modules and then the global node_modules to look for the module. It's not immediately clear though when you're just starting out learning node.js though. So I appreciate your answer. It was very clear and answered my problem. – Nicholas R. Grant Oct 20 '22 at 23:40