Skip to content

全局方法

一、常用方法

1 打印隐藏属性

js
console.dir(global, { showHidden: true });

2 打印进程

js
console.log(Object.keys(process));

3 获取设备

js
//  platform 开发脚手架,希望获取用户的配置信息 配置文件放到了用户的文件夹下
console.log(process.platform);

4 chdir 改变工作目录

js
process.chdir("./a"); // 可以修改代码执行时默认的执行路径

5 cwd

js
// cwd 当前工作目录 默认解析路径的时候 都是以这个路径为基础的,可以通过chdir来进行修改
console.log(process.cwd());

6 env

js
// .env 环境变量 我们开发的时候 根据用户提供的配置文件 来加载不同的环境
// dotenv   .env.prod   .env.dev  ( ini 格式)  (yaml)
console.log(process.env);

// windows set a=1
// mac linux  export a=1  临时的,窗口关闭就没有了
// cross-env 可以跨平台设置环境变量
// console.log(process.env.a); // 通过环境变量来让代码走到不同的逻辑

require("dotenv").config({
  path: process.env.NODE_ENV === "production" ? ".env.prod" : ".env.dev",
}); // 内部实现就是读取.env 文件

// cross-env + env 文件实现加载不同的环境变量来实现功能

7 argv

js
// argv 运行代码的时候传递的参数 vite --config my.config.js

console.log(process.argv.slice(2)); // 用户手动传递的参数 从第二个开始
// --config abc --directory efd
let result = process.argv.slice(2).reduce((memo, current, index, array) => {
  if (current.startsWith("--")) {
    memo[current.slice(2)] = array[index + 1]
      ? array[index + 1].startsWith("--")
        ? true
        : array[index + 1]
      : true;
  }
  return memo;
}, {});
console.log(result);

8 三方包-命令行

自己开发脚手架 都会采用第三方模块来配和使用 minimist yargs commander

js
const { program } = require("commander");

const pkg = require("./package.json");
program.name(pkg.name);
program.usage("<command> [options]"); // 使用方式
program.version(pkg.version);
program
  .command("create")
  .description("create project")
  .option("-d, --directory <d>", "set directory", process.cwd())
  .action((value, { args }) => {
    console.log(value, args);
  });
program
  .command("serve")
  .description("start server")
  .option("-p, --port [p]", "set port", 3000)
  .action((value, { args }) => {
    console.log(value, args);
  });
program.on("--help", function () {
  console.log("\nRun vue <command> --help for detailed usage of given command");
});
program.parse();
// vue create xxx

二、事件环

nodejs 的事件环是靠libuv库来实现的,libuv 这个库实现了异步 i/o,利用多线程来实现的。这种方式是基于事件驱动,底层原理就是 利用多线程处理后,将将结果放到队列中, 开一个事件线程会去扫描,依次执行。

nodejs 模拟了一个浏览器的事件环,执行代码顺序和逻辑是一样的,只是事件的阶段划分不一致,在浏览器中写的宏任务代码都会放到一个宏任务队列中来处理,而 node 会将不同的异步任务会放到不同的宏任务队列中。

js
┌───────────────────────────┐
┌─>│ timers │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ pending callbacks │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ idle, prepare │
│ └─────────────┬─────────────┘ ┌───────────────┐
│ ┌─────────────┴─────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └─────────────┬─────────────┘ │ data, etc. │
│ ┌─────────────┴─────────────┐ └───────────────┘
│ │ check │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
└──┤ close callbacks │
└───────────────────────────┘

宏任务

  • timers 放置定时器相关的逻辑(回调) ✅
  • peding callbacks 上一轮没执行完的 会在这一轮执行
  • idle prepare 内置的执行逻辑
  • poll 轮训 会在这里执行异步 i/o 文件读写 (如果执行完毕会阻塞) 如果都执行完后就关闭进程 ✅
  • check setImmediate 回调的 ✅
  • close callbacks 关闭的回调

PS: 老版本 node10 以下 是每个阶段走完后 清空微任务, 10 以上的版本和浏览器一致 (每执行一个宏任务就清空微任务)

js
setTimeout(() => {
  console.log("timer");
}, 0);
setImmediate(() => {
  console.log("setImmediate");
});

// 以上结果顺序不定,因为定时器执行时间不能确定
js
// prcoess.nextTick
// global.setImmediate

const fs = require("fs");
fs.readFile("./.env", function () {
  setTimeout(() => {
    console.log("timer");
  }, 0);
  setImmediate(() => {
    console.log("setImmediate");
  });
});

// poll -> check
// 执行结果如下:
// setImmediate
// timer
js
// prcoess.nextTick
// global.setImmediate

// poll -> check
Promise.resolve().then(() => {
  console.log("then");
});

process.nextTick(() => {
  // 当前宏任务执行后会执行的方法(微任务)
  console.log("next tick");
});

// next tick
// then

Released under the MIT License.