Node.js Common Interview Questions

1. Why is this in NodeJS an empty object?

Because all NodeJS files will be wrapped into a function when executed, this is changed to module.exports. (For details, please refer to the previous Node module principle analysis [detailed] article).
insert image description here
insert image description here

2. Why can exports, require, module, __filename, __dirname be used directly in NodeJS?

Because all NodeJS files will be wrapped into a function when they are executed, these properties are passed in the form of parameters.
// var args = [this.exports, require, module, filename, dirname];
// var result = compiledWrapper.call(this.exports, args);
will be wrapped into the following functions:

(function (exports, require, module, __filename, __dirname) {
exports.名 = 值;
});

3. In NodeJS, why can't exports be assigned directly, but can be assigned to module.exports?

<!--
(function (exports, require, module, __filename, __dirname) {
    
    
    exports = "lnj";
});
jsScript.call(module.exports, module.exports);
return module.exports;

相当于
let exports = module.exports;
exports = "lnj";
return module.exports;

insert image description here
exports is a formal parameter, module.exports is passed to it, and both point to the same object. If you directly assign a value to exports (exports='aaa'), it is equivalent to modifying its pointing, but in the end it returns module.exports.
insert image description here
insert image description here

4. Should I use var/let or const when importing packages through require?

The purpose of importing a package is to use the package rather than modify it, so use const accept when importing a package.

5. The difference between require and import

Both import and require are used by modules. In ES6 , use export to export interfaces and use import to import modules. But in the node module , use module.exports/exports to export the interface, use require to import the module,

  1. Difference 1: The time of appearance is different .
    • require means loading/calling at runtime, so it can theoretically be used anywhere in the code.
    • import means loading at compile time (higher efficiency). Since it is loaded at compile time, the import command will be promoted to the head of the entire module.
    • The variable imported by import is read-only, the reference type is OK, and other modules can also read the changed value, but it is not recommended to modify it.
    • import is performed statically, expressions and variables cannot be used.
      // 报错
      import {
              
               'f' + 'oo' } from 'my_module';
      // 报错
      let module = 'my_module';
      import {
              
               foo } from module;
      
    • import is a Singleton pattern.
        import {
              
               foo } from 'my_module';
        import {
              
               bar } from 'my_module';
        // 等同于
        import {
              
               foo, bar } from 'my_module';
        // 虽然foo和bar在两个语句加载,但是他们对应的是同一个my_module实例
      
    • Singleton mode .
      That is, the singleton mode is a commonly used software design mode that belongs to the creation type. The class created by the method of singleton mode has only one instance in the current process (according to the needs, it is also possible to belong to the single column mode in a thread, such as: only use the same instance in the thread context).
      Definition: : Ensure that a class has only one instance, and provide a global access point (similar to node's global) to access it.
  2. The following modular specifications are different .
    • require is the introduction method of AMD specification.
    • import is a grammatical standard of ES6, if it is to be compatible with browsers, it must be converted into ES5 grammar.
  3. Nature
    • require is the assignment process . What is the content behind module.exports, what is the result of require, such as objects, numbers, strings, functions, etc., and then assign the result of require to a variable, which is equivalent to the portal of module.exports .
    • Import is a structural process , but currently all engines have not implemented import. We use babel in node to support ES6, and it is only transcoded from ES6 to ES5 before execution. The import syntax will be transcoded into require .
    • Although import is a syntax in es6, at present, all engines have not yet implemented import.
    • The import syntax will actually be transcoded to require. This is why using module.exports when exporting modules and using import when importing templates still works, because essentially, import will be transcoded into require to execute .

6. Browser event loop

6.1, JS is single-threaded

The code in JS is all serial, and it cannot be executed after the previous execution is completed.

6.2. Execution sequence

  1. The program will execute all synchronous codes sequentially from top to bottom.
  2. If asynchronous code is encountered during execution, the asynchronous code will be placed in the event loop .
  3. After all synchronous codes are executed, JS will continuously check whether the asynchronous codes in the event loop meet the conditions.
  4. Executes the asynchronous code that satisfies the condition once the condition is met.

6.3. Macro tasks and micro tasks

In the asynchronous code of JS, "MacroTask" and "MicroTask" are distinguished.

Macro task : Macro/big means, it can be understood as a relatively time-consuming and slow task.
Microtask : Micro/small means that it can be understood as a task that is relatively less time-consuming and slower.

6.4 Common macro tasks and micro tasks

Macro tasks : setTimeout, setInterval, setImmediate (IE unique)...
Micro tasks : Promise, MutationObserver, process.nextTick (node ​​unique)...

Note: All macro tasks and micro tasks will be placed in their own execution queue, that is, there is a macro task queue and a micro task queue. All tasks placed in the queue adopt the "first in first out principle", that is, if multiple tasks meet the conditions at the same time, they will be executed first and put in first .

6.5. Complete execution sequence

insert image description here
insert image description here

  1. All synchronous code is executed from top to bottom.
  2. Execute all code in the microtask queue.
  3. Execute the conditional code in the macro task.
  4. Execute all code in the microtask queue.
  5. Execute the conditional code in the macro task.
    ...

Every time a macro task is executed, it will immediately check whether the micro task queue has been emptied, and if not, it will be emptied immediately

Attachments:
1. setImmediate (exclusive to IE browser) insert image description here
2. MutationObserver is a special monitoring node change
insert image description here

// html
<body>
<div></div>
<button class="add">添加节点</button>
<button class="del">删除节点</button>
</body>

// js
let oDiv = document.querySelector("div");
    let oAddBtn = document.querySelector(".add");
    let oDelBtn = document.querySelector(".del");
    oAddBtn.onclick = function () {
    
    
        let op = document.createElement("p");
        op.innerText = "我是段落";
        oDiv.appendChild(op);
    }
    oDelBtn.onclick = function () {
    
    
        let op = document.querySelector("p");
        oDiv.removeChild(op);
    }
    let mb = new MutationObserver(function () {
    
    
        console.log("执行了");
    });
    mb.observe(oDiv, {
    
    
        "childList": true
    });
    console.log("同步代码Start");
    console.log("同步代码End");

insert image description here

7. NodeJS event loop (Event Loop)

7.1. Overview

Like the browser, NodeJS also has an event loop (Event Loop), but because the host environment and application scenarios of code execution are different, the event loops of the two are also different.

Further reading:
Event Loop is implemented using libuv in NodeJS.
Source address: https://github.com/libuv/libuv

7.2. Difference between NodeJS event loop and browser event loop

insert image description here

  1. The number of task queues is different.
    • The browser event loop has 2 event queues (macrotask queue and microtask queue).
    • The NodeJS event loop has 6 event queues.
  2. Microtask queues are different.
    • There is a queue dedicated to storing microtasks in the browser event loop.
    • There is no queue dedicated to storing microtasks in the NodeJS event loop.
  3. The timing of microtask execution is different.
    • Every time a macro task is executed in the browser event loop, the micro task queue will be cleared.
    • In the NodeJS event loop, the microtask queue will be cleared only when the synchronization code is executed and switched between other queues (the task queue will be cleared when the queue is switched).
  4. Different microtask priorities
    • In the browser event loop, if multiple microtasks meet the execution conditions at the same time, first-in-first-out is used.
    • In the NodeJS event loop, if multiple microtasks meet the execution conditions at the same time, they will be executed according to the priority.

7.3. Task queue in NodeJS

Figure 1:
insert image description here

  1. important point:

Unlike browsers, there is no concept of macro task queues and micro task queues.
Macrotasks are put into different queues, but none of the queues are queues for microtasks.
Microtasks are executed after executing synchronous code and queue switching.

When to switch queues?
The task queue will switch when the queue is empty (it has been executed or the condition is not met) or the number of executed callback functions reaches the threshold set by the system.

  1. Note:
    The process.nextTick microtask has a higher priority than the Promise.resolve microtask in NodeJS.

Figure 2: The complete execution sequence of NodeJS .
insert image description here
Note:
After executing the poll, it will check whether there is content in the check queue, and switch to check if there is. If there is no content in the check queue, it will check whether the timers have content, and switch to timers if there is. If both the check queue and the timers queue have no content, they will be blocked in poll to avoid resource waste.

7.4, NodeJS-EventLoop interview questions

/*
注意点: 如下代码输出的结果是随机的
        在NodeJS中指定的延迟时间是有一定的误差的, 所以导致了输出结果随机的问题
* */
/*
setTimeout(function () {
    console.log("setTimeout");
}, 0);
setImmediate(function () {
    console.log("setImmediate");
});
 */

// 但是在下面的代码中输出结果都是固定的,即无论setTimeout、setImmediate顺序怎样,都会先执行setImmediate代码。
const path = require("path");
const fs = require("fs");

fs.readFile(path.join(__dirname, "04.js"), function () {
    
    
    setTimeout(function () {
    
    
        console.log("setTimeout");
    }, 0);
    setImmediate(function () {
    
    
        console.log("setImmediate");
    });
});

reason:
insert image description here

8. Customize local and global packages

  1. What is a package?
    A package is a folder used to manage modules and various relationships between modules.

  2. package use
    npm install xxx install package
    const xxx = require(xxx); use package

8.1, package specification (understand)

  • package.json must be in the top-level directory of the package.
  • The binaries should be in the bin directory.
  • The JavaScript code should be in the lib directory.
  • Documentation should be in the doc directory.
  • Unit tests should be in the test directory.

8.2, package.json field analysis (understanding)

  • name: The name of the package, which must be unique and consists of lowercase English letters, numbers and underscores, and cannot contain spaces.
  • description: A brief description of the package.
  • version: A version string that conforms to the semantic version identification specification.
    • Major version number: when you make incompatible API changes.
    • Subversion number: When you do backward compatible functional additions.
    • Revision number: When you made a backward compatibility bugfix.
  • keywords: An array of keywords, usually used for searching.
  • maintainers: array of maintainers, each element should contain name, email (optional), web (optional) fields.
  • contributors: array of contributors, the format is the same as that of maintainers. The author of the package should be the first element of the contributors array.
  • bugs: The address for submitting bugs, which can be a website or an email address.
  • licenses: an array of licenses, each element should contain type (license name) and URL (address connected to the license text) fields.
  • repositories: An array of warehouse hosting addresses, each element must contain type (repository type, such as git), url (repository address) and path (relative to the path of the warehouse, optional) fields.
  • dependencies: The dependencies of the production environment package, a key array consisting of the name and version number of the package.
  • devDependencies: The dependencies of the development environment package, an associative array consisting of the package name and version number.
  • main : Specify the package entry file. If main is not configured, index.js will be used as the entry by default. If there is no index.js in the package, then main must be configured .
  • scripts : 1. Save some commonly used instructions, which can be run through npm run key. 2. Application scenario: Every time a js file is executed, parameters need to be passed, and the parameters passed each time are the same, so the operation of inputting instructions can be simplified by saving the instructions in the script. (A parameter can be passed when executing a file through an instruction, and the file can get this parameter through process.argv. scripts can simplify the execution of commands)
    insert image description here
    Executing npm run start is equivalent to executing node lgg.js name=lgg age= 3

8.3. Implementation steps of custom package

  1. Create a package folder.
  2. Initialize a package.json file.
  3. Initialize a package entry js file.
    Note: If main is not configured, index.js will be used as the entry by default. If there is no index.js in the package, then main must be configured.
  4. Configure the package.json file according to the package information.
    Note: scripts can help us remember instructions, and then execute the instructions through npm run xxx. If the name of the command is called start or test, it is not necessary to add run when executing it .

Global packages: Generally, global packages are toolkits such as nrm, yarn, cnpm, etc. The characteristics of toolkits require custom instructions.

  1. Add the bin attribute to package.json to tell the system which one needs to be executed when executing the global imperative. JS files.
  2. Add #!/usr/bin/envnode to the JS file executed by the global command. (node ​​environment execution)
  3. Putting the local package globally through npm link is convenient for us to debug .

insert image description here

insert image description here
First npm link
insert image description here

8.4、Publish the custom package to the official website

  1. Register an account at https://www.npmjs.com .
  2. First switch to the directory where the package is located, for example: 06\node_modules\lgg\
  3. Type npm addUser in the terminal.
  4. Type npm publish in the terminal.

Note: Before the third step, switch the source to the official website.
nrm ls;
nrm use npm;

Guess you like

Origin blog.csdn.net/weixin_44767973/article/details/127705276