最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

雙token無感刷新nodejs+React詳細解釋(保姆級教程)

 更新時間:2025年05月27日 09:42:58   作者:妄春山_1  
雙token系統(tǒng)可以更好地管理用戶的權限,這篇文章主要介紹了雙token無感刷新nodejs+React的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

雙token無感刷新是一種在Web開發(fā)中常用的安全及用戶體驗優(yōu)化技術。以下是對雙token無感刷新的詳細解釋:

一、基本概念

雙token無感刷新主要涉及兩種類型的token:Access Token(訪問令牌)和Refresh Token(刷新令牌)。

  • Access Token:用戶直接用于訪問受保護資源的憑證。有效期較短,通常幾分鐘到幾小時不等。一旦過期,用戶需要重新認證以獲取新的Access Token。即使Access Token被泄露,由于其有效期短,攻擊者利用它進行不當操作的時間窗口有限。
  • Refresh Token:用于在Access Token過期后或過期前的一定時間內重新獲取新的Access Token。有效期通常較長,甚至可以說是永久的,但出于安全考慮,一般會設置過期時間或使用次數(shù)限制。Refresh Token通常不會直接發(fā)送給客戶端,而是保存在服務器端或經過加密后存儲在客戶端本地(如localStorage或sessionStorage)。

二、工作原理

雙token無感刷新的核心在于自動在后臺處理Access Token的過期和刷新過程,而無需用戶重新登錄或感知到這一過程。具體流程如下:

  • 用戶通過用戶名(賬號)、密碼或其他認證方式向認證服務器請求授權。
  • 認證成功后,服務器返回Access Token和Refresh Token給前端。前端將這兩個Token保存到本地存儲中,以便在需要時使用。
  • 前端在訪問受保護資源時,將Access Token放入請求頭中發(fā)送給后端。
  • 如果Access Token有效,后端正常處理請求并返回結果。
  • 如果Access Token過期,后端會返回一個錯誤響應(如HTTP 401 Unauthorized)。
  • 前端在接收到錯誤響應后,自動在后臺使用Refresh Token向認證服務器請求新的Access Token。
  • 認證服務器驗證Refresh Token的有效性后,返回一個新的Access Token和(可選的)新的Refresh Token。
  • 前端更新本地存儲的Access Token和Refresh Token,并重新發(fā)起之前的請求。

三、實現(xiàn)方式

雙token無感刷新的實現(xiàn)通常依賴于前端和后端的配合。以下是一個簡化的實現(xiàn)流程:

  • 前端實現(xiàn)

    • 設置全局請求攔截器,在發(fā)送請求前檢查Access Token的有效性。
    • 如果Access Token即將過期或已過期,自動使用Refresh Token請求新的Access Token。
    • 更新本地存儲中的Access Token和Refresh Token。
    • 重新發(fā)起因Access Token過期而失敗的請求。
  • 后端實現(xiàn)

    • 提供一個用于刷新Token的接口,該接口接收Refresh Token作為參數(shù)。
    • 驗證Refresh Token的有效性,如果有效,則生成新的Access Token和(可選的)新的Refresh Token,并返回給客戶端。
    • 在受保護資源的訪問接口中驗證Access Token的有效性,并在其過期時返回相應的錯誤響應。

四、優(yōu)勢與應用場景

雙token無感刷新的優(yōu)勢在于提高了系統(tǒng)的安全性和用戶體驗。通過分離短期和長期的憑證,降低了Access Token被泄露的風險,同時避免了用戶因Token過期而頻繁重新登錄的麻煩。

這一機制廣泛應用于需要高安全性和良好用戶體驗的場景,如Web應用和移動應用。在這些場景中,雙token無感刷新能夠提升用戶在持續(xù)操作過程中的連貫性和安全性。

五、后端代碼解析(nodejs+express)

(1)app.js引入所需要的模塊 

//app.js
var createError = require('http-errors'); //用于創(chuàng)建各種HTTP錯誤
var express = require('express'); //引入express模塊
var path = require('path'); //用于處理文件和目錄的路徑
var cookieParser = require('cookie-parser'); //解析HTTP請求中的Cookie頭
var logger = require('morgan'); //用于將請求日志輸出到stdout或指定文件
var indexRouter = require('./routes/index'); //主路由
var usersRouter = require('./routes/users'); //用戶相關路由
var jwt = require("jsonwebtoken"); //引入jsonwebtoken模塊
var app = express();
var cors = require("cors")
app.use(cors()) //處理跨域

(2)自定義中間件,用于處理jwt驗證

//app.js
app.use((req, res, next) => {
  // 定義不需要驗證的路徑
  let pathArr = [
    '/userLogin',
    '/refresh',
    '/sendYzm',
    '/resetPassword',
    '/findUser',
    '/upload'
  ]

  // 如果請求路徑在不需要驗證的路徑中,直接調用next()繼續(xù)處理
  if (pathArr.includes(req.path)) {
    return next()
  }

  // 獲取請求頭中的accessToken和refreshToken
  const accessToken = req.headers.accesstoken
  const refreshToken = req.headers.refreshtoken


  // 判斷refreshToken是否過期
  try {
    jwt.verify(refreshToken, "MTHGH")
  } catch (error) {
    console.log(error);
    return res.status(403).send({ message: 'refreshToken驗證失敗' })
  }

  // 如果沒有accessToken 返回401
  if (!accessToken) {
    return res.status(401).send({ message: '未獲取到accessToken' })
  }
  // 驗證accessToken
  try {
    const user = jwt.verify(accessToken, "MTHGH")
    res.locals.user = user//將用戶信息存儲在res.locals中,供后續(xù)中間件使用
    return next()
  } catch (error) {
    return res.status(401).send({ message: 'accessToken驗證失敗' })
  }
})

(3)index.js所需引入模塊

// index.js
var express = require('express'); //引入了Express模塊
var router = express.Router(); //用于處理HTTP請求
const jwt = require('jsonwebtoken');  //實現(xiàn)用戶身份驗證和授權等功能

(4)封裝生成長token和短token的函數(shù)

// index.js
// 訪問令牌有效期
const ACCESS_TOKEN_EXPIRATION='1h'
// 刷新令牌有效期
const REFRESH_TOKEN_EXPIRATION='1d'
// 令牌密鑰
const SECRET_KEY="MTHGH"
// 這里創(chuàng)建了一個Map對象,用于存儲用戶名和對應的刷新令牌列表。這樣,當用戶登錄或刷新令牌時,可以跟蹤和驗證他們的刷新令牌。
const refreshTokenMap=new Map()

// 生成函數(shù)令牌
function generateToken(name,expiration){
  return jwt.sign({name},SECRET_KEY,{expiresIn:expiration})
}

// 封裝生成長token和短token
function getToken(name){
  let accessToken = generateToken(name,ACCESS_TOKEN_EXPIRATION)
  let refreshToken = generateToken(name,REFRESH_TOKEN_EXPIRATION)
  const refreshTokens = refreshTokenMap.get(name)||[]
  refreshTokens.push(refreshToken)
  refreshTokenMap.set(name,refreshTokens)
  return {
    accessToken,
    refreshToken
  }
}

(5)賬號密碼登錄

// index.js
router.post('/userLogin', async (req, res) => {
  // 獲取前端傳遞的數(shù)據(jù)
  const {username,password} = req.body
  // 通過用戶查找是否存在
  let user = await userModel.findOne({userName:username})
  // 不存在
  if(!user){
    return res.status(200).send({message:"賬號錯誤",code:1})
  }
  // 用戶存在,密碼不正確
  if(user.passWord!==password){
    return res.status(200).send({message:"密碼錯誤",code:2})
  }
  // 調用函數(shù),生成token
  let {accessToken,refreshToken}=getToken(user.userName)
  // 返回用戶、token
  res.status(200).send({
    data:user,
    accessToken,
    refreshToken,
    message:'登陸成功',
    code:200
  })
})

(6)刷新短token

// index.js
router.get('/refresh',async(req,res)=>{
  // 獲取請求頭的token信息
  const refreshToken = req.headers.refreshtoken
  // token不存在
  if(!refreshToken){
    res.status(403).send("沒有短token")
  }
  // 驗證token是否過期
  try{
    const {name} = jwt.verify(refreshToken,SECRET_KEY)
    const accessToken = generateToken(name,ACCESS_TOKEN_EXPIRATION)
    res.status(200).send({accessToken})
  }catch(error){
    console.log('長token已經過期');
    res.status(403).send('長token已經過期')
  }
})

六、前端代碼解析(React)

(1)添加axios重試機制

// api.jsx
let retryCount = 0; // 初始化重試計數(shù)
const customRetryCondition = async (error) => {
  // 自定義重試條件
  if (axios.isAxiosError(error) && error.response?.status !== 200) {
    // 如果是 Axios 錯誤且響應狀態(tài)不是 200
    if (error.response?.status === 403) {
      // 如果后端返回 403(禁止訪問)
      localStorage.removeItem('accessToken'); // 移除 accessToken
      localStorage.removeItem('refreshToken'); // 移除 refreshToken
      console.log('請重新登錄'); // 打印提示信息
      window.location.href='/login' // 跳轉到登錄頁面
      return false; // 不重試
    }

    if (error.response?.status === 401) {
      // 如果后端返回 401(未授權)
      await refresh(); // 嘗試刷新 token
      console.log('刷新token'); // 打印提示信息
      return true; // 允許重試
    }

    retryCount++; // 增加重試計數(shù)
    console.log(`第${retryCount}次重試`); // 打印當前重試次數(shù)
    return (
      error.response.status >= 500 || // 如果響應狀態(tài)是 500 或以上
      (error.response.status < 500 && error.response?.status !== 401) // 或者狀態(tài)小于 500 但不等于 401
    );
  }
  return false; // 如果不符合條件,則不重試
};
// 配置 axios 實例的重試機制
axiosRetry(instance, {
  retries: 3, // 設置最多重試次數(shù)為 3 次
  retryCondition: customRetryCondition, // 使用自定義的重試條件
  retryDelay: axiosRetry.exponentialDelay, // 使用指數(shù)退避算法設置重試延遲
});

(2)axios添加請求攔截器

// api.jsx
// 請求攔截器
instance.interceptors.request.use(
  async function (config) {
    console.log('開始請求'); // 打印請求開始信息
    const accessToken = localStorage.getItem('accessToken'); // 從 localStorage 獲取 accessToken
    const refreshToken = localStorage.getItem('refreshToken'); // 從 localStorage 獲取 refreshToken
    console.log(accessToken);
    console.log(refreshToken);
    
    
    config.headers['accessToken'] = accessToken // 設置請求頭中的 accessToken
    config.headers['refreshToken'] = refreshToken // 設置請求頭中的 refreshToken
    return config; // 返回配置
  },
  function (error) {
    return Promise.reject(error); // 拒絕請求錯誤
  }
);

(3)axios添加響應攔截器

// api.jsx
/**
 * 響應攔截器
 */
instance.interceptors.response.use(
  async function (response) {
    // alert(222)
    if (response.status === 200) {
      
      return response; // 如果響應狀態(tài)是 200,返回響應
    } else {
      return Promise.reject(response.data.message || '未知錯誤'); // 否則拒絕并返回錯誤信息
    }
  },
  function (error) {
    if (error && error.response) {
      // 如果有響應錯誤
      switch (error.response.status) {
        case 400:
          error.message = '錯誤請求'; // 處理 400 錯誤
          break;
        case 401:
          error.message = '未授權,請重新登錄'; // 處理 401 錯誤
          break;
        case 403:
          error.message = '拒絕訪問'; // 處理 403 錯誤
          localStorage.removeItem('accessToken'); // 移除 accessToken
          localStorage.removeItem('refreshToken'); // 移除 refreshToken
          
          // Router.push('/login'); // 跳轉到登錄頁面
          window.location.href='/login'
          break;
        case 404:
          error.message = '請求錯誤,未找到該資源'; // 處理 404 錯誤
          break;
        case 405:
          error.message = '請求方法未允許'; // 處理 405 錯誤
          break;
        case 408:
          error.message = '請求超時'; // 處理 408 錯誤
          break;
        case 500:
          error.message = '服務器端出錯'; // 處理 500 錯誤
          break;
        case 501:
          error.message = '網絡未實現(xiàn)'; // 處理 501 錯誤
          break;
        case 502:
          error.message = '網絡錯誤'; // 處理 502 錯誤
          break;
        case 503:
          error.message = '服務不可用'; // 處理 503 錯誤
          break;
        case 504:
          error.message = '網絡超時'; // 處理 504 錯誤
          break;
        case 505:
          error.message = 'http版本不支持該請求'; // 處理 505 錯誤
          break;
        default:
          error.message = `連接錯誤${error.response.status}`; // 處理其他未知錯誤
      }
    } else {
      error.message = '連接服務器失敗'; // 如果沒有響應,打印連接失敗信息
    }
    return Promise.reject(error.message); // 拒絕并返回錯誤信息
  }
);

(4)刷新token

// api.jsx
// 重新刷新token
 async function refresh() {
  let res =await instance.get('/refresh'); // 發(fā)送請求以刷新 token
  localStorage.setItem('accessToken', res.data.accessToken); // 將新的 accessToken 存儲到 localStorage
}

七、后端完整代碼

(1)app.js

// app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var jwt = require("jsonwebtoken");
var app = express();
// cors
var cors = require("cors")
app.use(cors())

// 自定義中間件 用于處理jwt驗證
app.use((req, res, next) => {
  // 定義不需要驗證的路徑
  let pathArr = [
    '/userLogin',
    '/refresh',
    '/sendYzm',
    '/resetPassword',
    '/findUser',
    '/upload'
  ]

  // 如果請求路徑在不需要驗證的路徑中,直接調用next()繼續(xù)處理
  if (pathArr.includes(req.path)) {
    return next()
  }

  // 獲取請求頭中的accessToken和refreshToken
  const accessToken = req.headers.accesstoken
  const refreshToken = req.headers.refreshtoken


  // 判斷refreshToken是否過期
  try {
    jwt.verify(refreshToken, "MTHGH")
  } catch (error) {
    console.log(error, 111);
    return res.status(403).send({ message: 'refreshToken驗證失敗' })
  }

  // 如果沒有accessToken 返回401
  if (!accessToken) {
    return res.status(401).send({ message: '未獲取到accessToken' })
  }
  // 使用中間件
  // app.use('/index',validateRefreshToken,validateAccessToken)
  // app.use('/user',validateRefreshToken,validateAccessToken)
  // 驗證accessToken
  try {
    const user = jwt.verify(accessToken, "MTHGH")
    res.locals.user = user//將用戶信息存儲在res.locals中,供后續(xù)中間件使用
    return next()
  } catch (error) {
    return res.status(401).send({ message: 'accessToken驗證失敗' })
  }
})


// token
// var expressJWT = require("express-jwt")
// app.use(expressJWT({
//     secret: "123",
//     algorithms: ["HS256"]
// }).unless({
//     path: ["/login", "/upload", {url: /^\/upload/, methods: ['GET']}]
// }))

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/upload', express.static(path.join(__dirname, 'upload')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

(2)index.js

// index.js
var express = require('express');
var router = express.Router();
const jwt = require('jsonwebtoken');

var { userModel } = require("../model/model")
const app = express();
app.use(express.json()); // 解析請求中的 JSON 數(shù)據(jù)

// 訪問令牌有效期
const ACCESS_TOKEN_EXPIRATION='1h'
// 刷新令牌有效期
const REFRESH_TOKEN_EXPIRATION='1d'
const SECRET_KEY="MTHGH"
const refreshTokenMap=new Map()

// 生成函數(shù)令牌
function generateToken(name,expiration){
  return jwt.sign({name},SECRET_KEY,{expiresIn:expiration})
}

// 封裝生成長token和短token
function getToken(name){
  let accessToken = generateToken(name,ACCESS_TOKEN_EXPIRATION)
  let refreshToken = generateToken(name,REFRESH_TOKEN_EXPIRATION)
  const refreshTokens = refreshTokenMap.get(name)||[]
  refreshTokens.push(refreshToken)
  refreshTokenMap.set(name,refreshTokens)
  return {
    accessToken,
    refreshToken
  }
}

// 賬號密碼登錄
router.post('/userLogin', async (req, res) => {
  const {username,password} = req.body
  let user = await userModel.findOne({userName:username})
  if(!user){
    return res.status(200).send({message:"賬號錯誤",code:1})
  }
  if(user.passWord!==password){
    return res.status(200).send({message:"密碼錯誤",code:2})
  }
  let {accessToken,refreshToken}=getToken(user.userName)
  res.status(200).send({
    data:user,
    accessToken,
    refreshToken,
    message:'登陸成功',
    code:200
  })
})

// 刷新短token
router.get('/refresh',async(req,res)=>{
  const refreshToken = req.headers.refreshtoken
  // console.log(111);
  
  if(!refreshToken){
    res.status(403).send("沒有短token")
  }
  try{
    const {name} = jwt.verify(refreshToken,SECRET_KEY)
    const accessToken = generateToken(name,ACCESS_TOKEN_EXPIRATION)
    res.status(200).send({accessToken})
  }catch(error){
    console.log('長token已經過期');
    res.status(403).send('長token已經過期')
    
  }
})

module.exports = router;

八、前端完整代碼

(1)api.jsx

// api.jsx
import axios from "axios";
import axiosRetry from 'axios-retry';

// 基礎配置
const instance = axios.create({
  baseURL: "http://localhost:3010",
  timeout: 5000,
  headers: { 'Content-Type': 'application/json' },
});

/**
 * 重試機制
 */
let retryCount = 0; // 初始化重試計數(shù)
const customRetryCondition = async (error) => {
  // 自定義重試條件
  if (axios.isAxiosError(error) && error.response?.status !== 200) {
    // 如果是 Axios 錯誤且響應狀態(tài)不是 200
    if (error.response?.status === 403) {
      // 如果后端返回 403(禁止訪問)
      localStorage.removeItem('accessToken'); // 移除 accessToken
      localStorage.removeItem('refreshToken'); // 移除 refreshToken
      console.log('請重新登錄'); // 打印提示信息
      window.location.href='/login' // 跳轉到登錄頁面
      return false; // 不重試
    }

    if (error.response?.status === 401) {
      // 如果后端返回 401(未授權)
      await refresh(); // 嘗試刷新 token
      console.log('刷新token'); // 打印提示信息
      return true; // 允許重試
    }

    retryCount++; // 增加重試計數(shù)
    console.log(`第${retryCount}次重試`); // 打印當前重試次數(shù)
    return (
      error.response.status >= 500 || // 如果響應狀態(tài)是 500 或以上
      (error.response.status < 500 && error.response?.status !== 401) // 或者狀態(tài)小于 500 但不等于 401
    );
  }
  return false; // 如果不符合條件,則不重試
};

// 配置 axios 實例的重試機制
axiosRetry(instance, {
  retries: 3, // 設置最多重試次數(shù)為 3 次
  retryCondition: customRetryCondition, // 使用自定義的重試條件
  retryDelay: axiosRetry.exponentialDelay, // 使用指數(shù)退避算法設置重試延遲
});

// 請求攔截器
instance.interceptors.request.use(
  async function (config) {
    console.log('開始請求'); // 打印請求開始信息
    const accessToken = localStorage.getItem('accessToken'); // 從 localStorage 獲取 accessToken
    const refreshToken = localStorage.getItem('refreshToken'); // 從 localStorage 獲取 refreshToken
    console.log(accessToken);
    console.log(refreshToken);
    
    
    config.headers['accessToken'] = accessToken // 設置請求頭中的 accessToken
    config.headers['refreshToken'] = refreshToken // 設置請求頭中的 refreshToken
    return config; // 返回配置
  },
  function (error) {
    return Promise.reject(error); // 拒絕請求錯誤
  }
);

/**
 * 響應攔截器
 */
instance.interceptors.response.use(
  async function (response) {
    // alert(222)
    if (response.status === 200) {
      
      return response; // 如果響應狀態(tài)是 200,返回響應
    } else {
      return Promise.reject(response.data.message || '未知錯誤'); // 否則拒絕并返回錯誤信息
    }
  },
  function (error) {
    if (error && error.response) {
      // 如果有響應錯誤
      switch (error.response.status) {
        case 400:
          error.message = '錯誤請求'; // 處理 400 錯誤
          break;
        case 401:
          error.message = '未授權,請重新登錄'; // 處理 401 錯誤
          break;
        case 403:
          error.message = '拒絕訪問'; // 處理 403 錯誤
          localStorage.removeItem('accessToken'); // 移除 accessToken
          localStorage.removeItem('refreshToken'); // 移除 refreshToken
          
          // Router.push('/login'); // 跳轉到登錄頁面
          window.location.href='/login'
          break;
        case 404:
          error.message = '請求錯誤,未找到該資源'; // 處理 404 錯誤
          break;
        case 405:
          error.message = '請求方法未允許'; // 處理 405 錯誤
          break;
        case 408:
          error.message = '請求超時'; // 處理 408 錯誤
          break;
        case 500:
          error.message = '服務器端出錯'; // 處理 500 錯誤
          break;
        case 501:
          error.message = '網絡未實現(xiàn)'; // 處理 501 錯誤
          break;
        case 502:
          error.message = '網絡錯誤'; // 處理 502 錯誤
          break;
        case 503:
          error.message = '服務不可用'; // 處理 503 錯誤
          break;
        case 504:
          error.message = '網絡超時'; // 處理 504 錯誤
          break;
        case 505:
          error.message = 'http版本不支持該請求'; // 處理 505 錯誤
          break;
        default:
          error.message = `連接錯誤${error.response.status}`; // 處理其他未知錯誤
      }
    } else {
      error.message = '連接服務器失敗'; // 如果沒有響應,打印連接失敗信息
    }
    return Promise.reject(error.message); // 拒絕并返回錯誤信息
  }
);

// 重新刷新token
 async function refresh() {
  let res =await instance.get('/refresh'); // 發(fā)送請求以刷新 token
  localStorage.setItem('accessToken', res.data.accessToken); // 將新的 accessToken 存儲到 localStorage
}

// 導出封裝后的 axios 實例
export default instance;

綜上所述,雙token無感刷新是一種有效的安全及用戶體驗優(yōu)化技術,通過合理的Token管理和自動刷新機制,實現(xiàn)了在不影響用戶體驗的前提下提升系統(tǒng)安全性的目標。

總結

到此這篇關于雙token無感刷新nodejs+React的文章就介紹到這了,更多相關雙token無感刷新nodejs+React內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • node.js 利用流實現(xiàn)讀寫同步,邊讀邊寫的方法

    node.js 利用流實現(xiàn)讀寫同步,邊讀邊寫的方法

    下面小編就為大家?guī)硪黄猲ode.js 利用流實現(xiàn)讀寫同步,邊讀邊寫的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • nodejs實現(xiàn)遍歷文件夾并統(tǒng)計文件大小

    nodejs實現(xiàn)遍歷文件夾并統(tǒng)計文件大小

    這篇文章主要介紹了nodejs實現(xiàn)遍歷文件夾并統(tǒng)計文件大小,下面使用nodejs的遍歷文件夾文件內容,并且讀取所有的文件,并采取排序往大到小的順序進行輸出,需要的朋友可以參考下
    2015-05-05
  • 前端Electron新手入門教程詳解

    前端Electron新手入門教程詳解

    這篇文章主要介紹了Electron新手入門教程詳解,首先圍繞Electron框架的關鍵知識點進行詳細講解,然后對DEMO程序進行分析,讓前端開發(fā)人員對使用Electron開發(fā)桌面應用程序有一個初步的了解。,需要的朋友可以參考下
    2019-06-06
  • windows使用nvm對node進行版本管理切換的完整步驟

    windows使用nvm對node進行版本管理切換的完整步驟

    這篇文章主要介紹了windows使用nvm對node進行版本管理切換的完整步驟,在使用之前各位務必卸載掉自己安裝過的nvm或者node版本包括環(huán)境變量之類的,要保證自己的電腦完全沒有node環(huán)境,需要的朋友可以參考下
    2024-03-03
  • Node.js插件的正確編寫方式

    Node.js插件的正確編寫方式

    正如Node.js在官方說明文檔中所言,插件是以動態(tài)方式進行鏈接的共享式對象,能夠將JavaScript代碼與C/C++庫接駁起來。這意味著我們可以引用任何來自C/C++庫中的內容,并通過創(chuàng)建插件的方式將其納入到Node.js當中。
    2014-08-08
  • nodejs實現(xiàn)的http、https 請求封裝操作示例

    nodejs實現(xiàn)的http、https 請求封裝操作示例

    這篇文章主要介紹了nodejs實現(xiàn)的http、https 請求封裝操作,結合實例形式分析了node.js針對http、https 請求的封裝與使用相關操作技巧,需要的朋友可以參考下
    2020-02-02
  • 深入解析Node.js dns 模塊

    深入解析Node.js dns 模塊

    Node.js DNS模塊實現(xiàn)域名解析與IP反查,支持A、MX、TXT等記錄查詢,提供lookup(系統(tǒng)級)和resolve(網絡級)方法,兼容Promise API,可處理解析錯誤,適用于郵件路由、服務發(fā)現(xiàn)等場景,本文給大家介紹Node.js dns 模塊,感興趣的朋友一起看看吧
    2025-07-07
  • 安裝nodejs和yarn及配置淘寶源過程記錄

    安裝nodejs和yarn及配置淘寶源過程記錄

    這篇文章主要介紹了安裝nodejs和yarn及配置淘寶源過程記錄的相關資料,需要的朋友可以參考下
    2021-10-10
  • 淺探express路由和中間件的實現(xiàn)

    淺探express路由和中間件的實現(xiàn)

    這篇文章主要介紹了淺探express路由和中間件的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • 詳解如何使用koa實現(xiàn)socket.io官網的例子

    詳解如何使用koa實現(xiàn)socket.io官網的例子

    這篇文章主要介紹了詳解如何使用koa實現(xiàn)socket.io官網的例子,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11

最新評論

清水河县| 广安市| 辛集市| 湟源县| 武胜县| 绵阳市| 宜君县| 沙田区| 元谋县| 渭源县| 孝义市| 海城市| 陵水| 留坝县| 中牟县| 桃园市| 金塔县| 和政县| 滕州市| 阳曲县| 昆明市| 保靖县| 东乡| 疏勒县| 曲阳县| 枣强县| 普兰县| 五大连池市| 阜新市| 祁东县| 涞源县| 武义县| 巴东县| 师宗县| 涪陵区| 梨树县| 浮山县| 桐庐县| 潜山县| 宁晋县| 甘肃省|