ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Node.js
    Node.js 2021. 11. 9. 23:28

    이 글은 Node.js 사용을 위해 필요한 기본 지식들을 정리하기 위해 작성하였습니다.



    < Introduction >

    Node.js is a JavaScript runtime, or an environment that allows us to execute JavaScript code outside of the browser.

    Though Node was created with the goal of building web servers and web applications in JavaScript, it can also be used for creating command-line applications or desktop applications.

     

    Reference : Learnyounode

    https://github.com/workshopper/learnyounode

     

    GitHub - workshopper/learnyounode: Learn You The Node.js For Much Win! An intro to Node.js via a set of self-guided workshops.

    Learn You The Node.js For Much Win! An intro to Node.js via a set of self-guided workshops. - GitHub - workshopper/learnyounode: Learn You The Node.js For Much Win! An intro to Node.js via a set of...

    github.com

     


    < The Node REPL >

    REPL is an abbreviation for read–eval–print loop.

    It’s a program that loops, or repeatedly cycles, through three different states:
    1. a read state where the program reads input from a user,
    2. the eval state where the program evaluates the user’s input,
    3. and the print state where the program prints out its evaluation to a console. Then it loops through these states again.

     

    When you install Node, it comes with a built-in JavaScript REPL. You can access the REPL by typing the command node (with nothing after it) into the terminal and hitting enter.
    $ node
    >
    # '>' character indicate the REPL is running

     

    $ node
    > .editor
    // Entering editor mode (^D to finish, ^C to cancel)
    
    # If you’d like to type multiple lines and then have them evaluated at once you can type .editor while in the REPL​

     

    • Each session of the REPL has a single shared memory; you can access any variables or functions you define until you exit the REPL.
    • A REPL can be extremely useful for performing calculations, learning a language, and developing code.

     

     


    < Running a Program with Node >

    To run a program in Node.

     

    < Syntax >
    $ node 실행프로그램

     

    ex)

    // Inside myProgram.js
    console.log('Hello World');
    $ node myProgram.js
    Hello World

     

     


    < Accessing the Process Object >

    A process is the instance of a computer program that is being executed.

    Node has a global process object with useful methods and information about the current process.

     

    ex1 )

    The process.env object contains a PWD property which holds a string with the directory in which the current process is located.

    $ node
    > console.log(process.env.PWD);
    /home/ccuser/workspace/node-process

     

    ex 2)

    The process.memoryUsage() returns information on the CPU demands of the current process. It returns a property that looks similar to this:

    $ node
    > console.log(process.memoryUsage())
    { rss: 27549696,
      heapTotal: 6815744,
      heapUsed: 4448976,
      external: 9406 }

     

    ex 3)

    The process.argv property holds an array of command line values

    $ node
    > node myProgram.js testing several values
    > console.log(process.argv[3]);
    Several

     

    +. Node also has a useful global object that are available anywhere in the Node environment.

     

     


    < Core Modules and Local Modules >

    To save developers from having to reinvent the wheel each time, use modularity technique.

     

    < Core Modules >
    Node has several modules included within the environment to efficiently perform common tasks (a.k.a. core modules)
    : be required by passing a name of the module into require( ) function.

    < Local Modules >
    we can use the modules of our own creation (a.k.a. local modules)
    : be required by passing in the path to the module into require( ) function.

     

    ex)

    # Require in the 'events' core module :
    let events = require('events');
    
    # Require in the 'Dog' local module :
    let Dog = require('./dog.js');

     

     


    < Node Package Manager >

    In addition to local modules and core modules, we can take advantage of third-party modules.
    NPM, which stands for Node Package Manager, is an online collection, or registry, of software.
    Developers can share code they’ve written to the registry or download code provided by other developers.


    Using libraries created by other developers is an essential aspect of production; we don’t have to reinvent the wheel each time we want to include new functionality into our applications.

     

    • When we download Node, the npm command-line tool is downloaded as well, which enables us to interact with the registry via our terminal. There are hundreds of thousands of packages of re-usable code in the NPM registry including powerful and popular frameworks like express and react.
    • You can explore the collection at the npm website.
     

    npm

    Bring the best of open source to you, your team, and your company Relied upon by more than 11 million developers worldwide, npm is committed to making JavaScript development elegant, productive, and safe. The free npm Registry has become the center of Java

    www.npmjs.com

     

     


    < Event-Driven Architecture >

     to write logic to handle situations without knowing exactly when they’ll occur using EventEmitter Class.

     

    < Node provides an EventEmitter class which we can access by requiring in the events core module >
    // Require in the 'events' core module
    let events = require('events');
     
    // Create an instance of the EventEmitter class
    let myEmitter = new events.EventEmitter();


    < Each event emitter instance has .on( ) and .emit( ) functions >

    1. on( ) function : Assign the function as the listener callback for events.
    - first argument : the name of the event as a string.
    - second argument : the listener callback function.

    2. emit( ) function : Emit a event.
    - first argument : the name of the event as a string.
    - second argument : the data that should be passed into the listener function.


     

    ex)

    // Require in the 'events' core module
    let events = require('events');
     
    // Create an instance of the EventEmitter class
    let myEmitter = new events.EventEmitter();
    
    let newUserListener = (data) => {
      console.log(`We have a new user: ${data}.`);
    };
     
    // Assign the newUserListener function as the listener callback for 'new user' events
    myEmitter.on('new user', newUserListener)
     
    // Emit a 'new user' event
    myEmitter.emit('new user', 'Lily Pad') //newUserListener will be invoked with 'Lily Pad'

     

     


    < User Input/Output >

    Output is any data or feedback that a computer provides (like to a human user),
    while input is data provided to the computer.

     

    ex)

    process.stdin.on('data', (userInput) => {
      let input = userInput.toString()
      console.log(input)
    });

    : Here, we were able to use .on() because under the hood process.stdin is an instance of EventEmitter.

    When a user enters text into the terminal and hits enter, a 'data' event will be fired and our anonymous listener callback will be invoked.

     

     

    +. In Node, 'console.log' is 'process.stdout.write( )'

    reference : https://stackoverflow.com/questions/4976466/difference-between-process-stdout-write-and-console-log-in-node-js

     

     


    < Errors >

    With synchronous code in Node, we can use error handling techniques such as try...catch statements.
    But many asynchronous Node APIs use error-first callback functions.

     

    • Error-first callback functions : which have an error as the first expected argument and the data as the second argument.

     

    ex) Why traditional try...catch statements won’t work for errors thrown during asynchronous operations.

     

    < API.js >

    module.exports = {
      errorProneAsyncApi: (input, callback) => {
        console.log(`Running errorProneAsyncApi with input: ${input}...\n`)
        setTimeout(() => {
          let myErr;
          if (input === 'problematic input') {
            myErr = new Error('whoops')
            callback(myErr)
          } else {
            let responseData = `Received valid input "${input}"`
            callback(myErr, responseData)
          }
        }, 0)
      },
      
      naiveErrorProneAsyncFunction: (input, callback) => {
        console.log(`Running naiveErrorProneAsyncFunction with input: ${input}...\n`)
        setTimeout(() => {
          if (input === 'problematic input') {
            throw new Error('whoops')
          } else {
            let responseData = `Received valid input "${input}"`
            callback(responseData)
          }
        }, 0)
    }
      
    }

    < Not work file >

    const api = require('./api.js');
    
    // Not an error-first callback
    let callbackFunc = (data) => {
       console.log(`Something went right. Data: ${data}\n`);
    };
      
    try {
      api.naiveErrorProneAsyncFunction('problematic input', callbackFunc);
    } catch(err) {
      console.log(`Something went wrong. ${err}\n`);
    }
    
    // expected output
    // Something went wrong. ${err}\n
    
    // output
    // Error: whoops

    : Not Work, Because the error is thrown asynchronously.

     

    < work file >

    const api = require('./api.js');
    
    // An error-first callback
    let errorFirstCallback = (err, data) => {
      if (err) {
        console.log(`Something went wrong. ${err}\n`);
      } else {
        console.log(`Something went right. Data: ${data}\n`);
      }
    };
    
    api.errorProneAsyncApi('problematic input', errorFirstCallback);
    
    // output
    // Something went wrong. Error: whoops

     

     


    < Filesystem  >

    All of the data is organized and accessed through a filesystem.

    The Node fs core module is an API for interacting with the file system.

     

    ex)

    •  One method available on the fs core module is the .readFile() method which reads data from a provided file
    const fs = require('fs');
     
    let readDataCallback = (err, data) => {
      if (err) {
        console.log(`Something went wrong: ${err}`);
      } else {
        console.log(`Provided file contained: ${data}`);
      }
    };
     
    fs.readFile('./file.txt', 'utf-8', readDataCallback);
    
    // output if there is no error
    // Provided file contained: blahblahblah...

    first argument : path to the file

    second argument : specifying the file's character encoding ( usually 'utf-8' for text files)

    third argument : callback function to be invoked.

     

     


    < Stream >

    In realistic scenarios, data isn't processed all at once but rather sequentially, piece by piece, in what is known as a stream.
    Streaming data is often preferable since you don’t need enough RAM to process all the data at once nor do you need to have all the data on hand to begin processing it.

    One of the simplest uses of stream is reading and writing to files line-by-line.

     

    < Reading >

    Use .createInterface( ) and .createReadStream( ) method
    : .createInterface( ) returns an 'EventEmitter' set up

    ex)
    const readline = require('readline');
    const fs = require('fs');
    
    const myInterface = readline.createInterface({
      input: fs.createReadStream('shoppingList.txt')
      // create a stream form the 'shopping List' file
    })
    
    
    myInterface.on('line', (data) => {
    	console.log(`item: ${data}`);
        // a 'line' event will be emitted after each line from the file is read
    });

    output)
    $ node app.js
    item: apples
    item: pears
    item: royal jelly
    item: bread
    item: milk
    item: tofu
    item: beans
    item: flan
    item: pork
    item: tamarind

     

    < Writing >

    Use .createWriteStream( ) method
    : should end the stream with .end( ) method.

    ex)
    const fs = require('fs');
    
    const fileStream = fs.createWriteStream('output.txt');
    
    fileStream.write('This is the first line!');
    fileStream.write('This is the second line!');
    fileStream.end();

     

     


    < Create an HTTP Server >

    Node was designed with back end development needs as a top priority. One of these needs is the ability to create web servers, computer processes that listen for requests from clients and return responses.

    A Node core module designed to meet these needs is the http module. This module contains functions which simplify interacting with HTTP and streamline receiving and responding to requests.

     

    ex)

    const http = require('http');
     
    let requestListener = (request, response) => {
      response.writeHead(200, {'Content-Type': 'text/plain' });
      response.write('Hello World!\n');
      response.end();
    };
     
    const server = http.createServer(requestListener);
     
    server.listen(3000);

     

    const http = require('http');

    : Required in the http core module

    const server = http.createServer(requestListener);

    : created a server variable assigned to the return value of the http.createServer() method.

     

    < http.createServer( ) method >
    The http.createServer( ) method returns an instance of an http.server.
    An http.server has a method .listen( ) which causes the server to “listen” for incoming connections. When we run http.createServer() we pass in a custom callback function (often referred to as the requestListener). This callback function will be triggered once the server is listening and receives a request.

     

    let requestListener = (request, response) => {
      response.writeHead(200, {'Content-Type': 'text/plain' });
      response.write('Hello World!\n');
      response.end();
    };

    : Within the requestListener callback, we make changes to the response object, response, so that it can send the appropriate information to the client sending the request.

     

    < requestListener callback function >
    1. expects two arguments: a request object and a response object.
    2. The requestListener is responsible for setting the response header and body.
    3. The requestListener must signal that the interaction is complete by calling the response.end( ) method.

    : Each time a request to the server is made, Node will invoke the provided requestListener callback function, passing in the request and response objects of the incoming request.

     

    server.listen(3000);

    : The last line starts the server with the port 3000. Every server on a given machine specifies a unique port so that traffic can be correctly routed.

     

     

    Reference https://nodejs.org/api/http.html

     

    HTTP | Node.js v17.0.1 Documentation

    HTTP# Source Code: lib/http.js To use the HTTP server and client one must require('http'). The HTTP interfaces in Node.js are designed to support many features of the protocol which have been traditionally difficult to use. In particular, large, possibly c

    nodejs.org

     

     

     

     

     

     

     

     

    +. Asynchronous Javascript with Node.js (개인 참고용)

    자료 읽어보기 : https://www.codecademy.com/paths/full-stack-engineer-career-path/tracks/fscp-build-a-back-end-with-node-express-js/modules/fscp-learn-node-js/lessons/node/exercises/event-loop

     

     

     

     

     

    댓글

Designed by Tistory.