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

Node處理CPU密集型任務(wù)有哪些方法

 更新時間:2022年09月13日 08:31:19   作者:進擊的大蔥???????  
這篇文章主要介紹了Node處理CPU密集型任務(wù)有哪些方法,Node是一個非阻塞I/O和事件驅(qū)動的JavaScript運行環(huán)境,所以它非常適合用來構(gòu)建I/O密集型應(yīng)用,例如Web服務(wù)等

背景介紹

我們?nèi)粘9ぷ髦谢蚨嗷蛏俾犝f過以下的話:

Node是一個非阻塞I/O(non-blocking I/O)和事件驅(qū)動(event-driven)的JavaScript運行環(huán)境(runtime),所以它非常適合用來構(gòu)建I/O密集型應(yīng)用,例如Web服務(wù)等。

不知道當(dāng)你聽到類似的話時會不會有和我一樣的疑惑:單線程的Node為什么適合用來開發(fā)I/O密集型應(yīng)用?按道理來說不是那些支持多線程的語言(例如Java和Golang)做這些工作更加有優(yōu)勢嗎?

要搞明白上面的問題,我們需要知道Node的單線程指的是什么。

Node不是單線程的

其實我們說Node是單線程的,說的只是我們的JavaScript代碼是在同一個線程(我們可以叫它主線程)里面運行的,而不是說Node只有一個線程在工作。實際上Node底層會使用libuv的多線程能力將一部分工作(基本都是I/O相關(guān)操作)放在一些主線程之外的線程里面執(zhí)行,當(dāng)這些任務(wù)完成后再以回調(diào)函數(shù)的方式將結(jié)果返回到主線程的JavaScript執(zhí)行環(huán)境。

可以看看示意圖:

注: 上圖是Node事件循環(huán)(Event Loop)的簡化版,實際上完整的事件循環(huán)會有更多的階段例如timers等。

Node適合做I/O密集型應(yīng)用

從上面的分析中我們知道Node會將所有的I/O操作通過libuv的多線程能力分散到不同的線程里面執(zhí)行,其余的操作都放在主線程里面執(zhí)行。那么為什么這種做法就比Java或者Golang等其它語言更適合做I/O密集型應(yīng)用呢?我們以開發(fā)Web服務(wù)為例,Java和Golang等主流后端編程語言的并發(fā)模型是基于線程(Thread-Based)的,這也就意味他們對于每一個網(wǎng)絡(luò)請求都會創(chuàng)建一個單獨的線程來處理。可是對于Web應(yīng)用來說,主要還是對數(shù)據(jù)庫的增刪改查,或者請求其它外部服務(wù)等網(wǎng)絡(luò)I/O操作,而這些操作最后都是交給操作系統(tǒng)的系統(tǒng)調(diào)用來處理的(無需應(yīng)用線程參與),并且十分緩慢(相對于CPU時鐘周期來說),因此被創(chuàng)建出來的線程大多數(shù)時間是無事可做的而且我們的服務(wù)還要承擔(dān)額外的線程切換開銷。和這些語言不一樣的是Node沒有為每個請求都創(chuàng)建一個線程,所有請求的處理都發(fā)生在主線程中,因此沒有了線程切換的開銷,并且它還會通過線程池的形式異步處理這些I/O操作,然后通過事件的形式告訴主線程結(jié)果從而避免阻塞主線程的執(zhí)行,因此它理論上是更高效的。這里值得注意的是我只是說Node理論上是更快的,實際上真不一定。這是因為現(xiàn)實中一個服務(wù)的性能會受到很多方面的影響,我們這里只是考慮了并發(fā)模型這一個因素,而其它因素例如運行時消耗也會影響到服務(wù)的性能,舉個例子,JavaScript是動態(tài)語言,數(shù)據(jù)的類型需要在運行時進行推斷,而GolangJava都是靜態(tài)語言它們的數(shù)據(jù)類型在編譯時就可以確定,所以它們實際執(zhí)行起來可能會更快,占用內(nèi)存也會更少。

Node不適合做CPU密集型任務(wù)

上面我們提到Node除了I/O相關(guān)的操作其余操作都會在主線程里面執(zhí)行,所以當(dāng)Node要處理一些CPU密集型的任務(wù)時,主線程會被阻塞住。我們來看一個CPU密集型任務(wù)的例子:

// node/cpu_intensive.js

const http = require('http')
const url = require('url')

const hardWork = () => {
  // 100億次毫無意義的計算
  for (let i = 0; i < 10000000000; i++) {}
}
const server = http.createServer((req, resp) => {
  const urlParsed = url.parse(req.url, true)

  if (urlParsed.pathname === '/hard_work') {
    hardWork()
    resp.write('hard work')
    resp.end()
  } else if (urlParsed.pathname === '/easy_work') {
    resp.write('easy work')
    resp.end()
  } else {
    resp.end()
  }
})
server.listen(8080, () => {
  console.log('server is up...')
})

在上面的代碼中我們實現(xiàn)了擁有兩個接口的HTTP服務(wù):/hard_work接口是一個CPU密集型接口,因為它調(diào)用了hardWork這個CPU密集型函數(shù),而/easy_work這個接口則很簡單,直接返回一個字符串給客戶端就可以了。為什么說hardWork函數(shù)是CPU密集型的呢?這是因為它都是在CPU的運算器里面對i進行算術(shù)運算而沒有進行任何I/O操作。啟動完我們的Node服務(wù)后,我們試著調(diào)用一下/hard_word接口:

我們可以看到/hard_work接口是會卡住的,這是因為它需要進行大量的CPU計算,所以需要比較久的時間才會執(zhí)行完。而這個時候我們再看一下/easy_work這個接口有沒有影響:

我們發(fā)現(xiàn)在/hard_work占用了CPU資源之后,無辜的/easy_work接口也被卡死了。原因就是hardWork函數(shù)阻塞了Node的主線程導(dǎo)致/easy_work的邏輯不會被執(zhí)行。這里值得一提的是,只有Node這種基于事件循環(huán)的單線程執(zhí)行環(huán)境才會有這種問題,Java和Golang等Thread-Based語言是不會存在這種問題的。那如果我們的服務(wù)真的需要運行CPU密集型任務(wù)怎么辦?總不能換門語言吧?說好的All in JavaScript呢?別著急,對于處理CPU密集型任務(wù),Node已經(jīng)為我們準備好很多方案了,接下來就讓我為大家介紹三種常用的方案,它們分別是: Cluster ModuleChild ProcessWorker Thread。

Cluster Module

概念介紹

Node很早(v0.8版本)就推出了Cluster模塊。這個模塊的作用就是通過一個父進程啟動一群子進程來對網(wǎng)絡(luò)請求進行負載均衡。因為文章的篇幅限制我們不會細聊Cluster模塊有哪些API,感興趣的讀者后面可以看看官方文檔,

這里我們直接看一下如何使用Cluster模塊來優(yōu)化上面CPU密集型的場景:

// node/cluster.js

const cluster = require('cluster')
const http = require('http')
const url = require('url')

// 獲取CPU核數(shù)
const numCPUs = require('os').cpus().length

const hardWork = () => {
  // 100億次毫無意義的計算
  for (let i = 0; i < 10000000000; i++) {}
}

// 判斷當(dāng)前是否是主進程
if (cluster.isMaster) {
  // 根據(jù)當(dāng)前機器的CPU核數(shù)創(chuàng)建同等數(shù)量的工作進程
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork()
  }

  cluster.on('online', (worker) => {
    console.log(`worker ${worker.process.pid} is online`)
  })

  cluster.on('exit', (worker, code, signal) => {
    // 某個工作進程掛了之后,我們需要立馬啟動另外一個工作進程來替代
    console.log(`worker ${worker.process.pid} exited with code $[code], and signal ${signal}, start a new one...`)
    cluster.fork()
  })
} else {
  // 工作進程啟動一個HTTP服務(wù)器
  const server = http.createServer((req, resp) => {
    const urlParsed = url.parse(req.url, true)
  
    if (urlParsed.pathname === '/hard_work') {
      hardWork()
      resp.write('hard work')
      resp.end()
    } else if (urlParsed.pathname === '/easy_work') {
      resp.write('easy work')
      resp.end()
    } else {
      resp.end()
    }
  })

  // 所有的工作進程都監(jiān)聽在同一個端口
  server.listen(8080, () => {
    console.log(`worker ${process.pid} server is up...`)
  })
}

在上面的代碼中我們根據(jù)當(dāng)前設(shè)備的CPU核數(shù)使用cluster.fork函數(shù)創(chuàng)建了同等數(shù)量的工作進程,而且這些工作進程都是監(jiān)聽在8080端口上面的??吹竭@里你或許會問所有的進程都監(jiān)聽在同一個端口會不會出現(xiàn)問題,這里其實是不會的,因為Cluster模塊底層會做一些工作讓最終監(jiān)聽在8080端口的是主進程,而主進程是所有流量的入口,它會接收HTTP連接并把它們打到不同的工作進程上面。話不多說,讓我們運行一下這個node服務(wù):

從上面的輸出結(jié)果來看,cluster啟動了10個worker(我的電腦是10核的)來處理web請求,這個時候我們再來請求一下/hard_work這個接口:

我們發(fā)現(xiàn)這個請求還是卡死的,接著我們再來看看Cluster模塊有沒有解決其它請求也被阻塞的問題:

我們可以看到前面9個請求都是很順利就返回結(jié)果的,可是到了第10個請求我們的接口就卡住了,這是為什么呢?原因就是我們一共開了10個工作進程,主進程在將流量打到子進程的時候采用的默認負載均衡策略是round-robin(輪流),因此第10個請求(其實是第11個,因為包括了第一個hard_work的請求)剛好回到第一個worker,而這個worker還沒處理完hard_work的任務(wù),因此這個easy_work的任務(wù)也就卡住了。cluster的負載均衡算法可以通過cluster.schedulingPolicy來修改,有興趣的讀者可以看一下官方文檔。

從上面的結(jié)果來看Cluster Module似乎解決了一部分我們的問題,可是還是有一些請求受到了影響。那么Cluster Module在實際開發(fā)里面能不能被用來解決這個CPU密集型任務(wù)的問題呢?我的意見是:看情況。如果你的CPU密集型接口調(diào)用不頻繁而且運算時間不會太長,你完全可以使用這種Cluster Module來優(yōu)化??墒侨绻愕慕涌谡{(diào)用頻繁并且每個接口都很耗時間的話,可能你需要看一下采用Child Process或者Worker Thread的方案了。

Cluster Module的優(yōu)缺點

最后我們總結(jié)一下Cluster Module有什么優(yōu)點:

  • 資源利用率高:可以充分利用CPU的多核能力來提升請求處理效率。
  • API設(shè)計簡單:可以讓你實現(xiàn)簡單的負載均衡一定程度的高可用。這里值得注意的是我說的是一定程度的高可用,這是因為Cluster Module的高可用是單機版的,也就是當(dāng)宿主機器掛了,你的服務(wù)也就掛了,因此更高的高可用肯定是使用分布式集群做的。
  • 進程之間高度獨立,避免某個進程發(fā)生系統(tǒng)錯誤導(dǎo)致整個服務(wù)不可用。

優(yōu)點說完了,我們再來說一下Cluster Module不好的地方:

  • 資源消耗大:每一個子進程都是獨立的Node運行環(huán)境,也可以理解為一個獨立的Node程序,因此占用的資源也是巨大的。
  • 進程通信開銷大:子進程之間的通信通過跨進程通信(IPC)來進行,如果數(shù)據(jù)共享頻繁是一筆比較大的開銷。
  • 沒能完全解決CPU密集任務(wù):處理CPU密集型任務(wù)時還是有點抓緊見肘

Child Process

在Cluster Module中我們可以通過啟動更多的子進程來將一些CPU密集型的任務(wù)負載均衡到不同的進程里面,從而避免其余接口卡死??墒悄阋部吹搅耍@個辦法治標(biāo)不治本,如果用戶頻繁調(diào)用CPU密集型的接口,那么還是會有一大部分請求會被卡死的。優(yōu)化這個場景的另外一個方法就是child_process模塊。

概念介紹

Child Process可以讓我們啟動子進程來完成一些CPU密集型任務(wù)。我們先來看一下主進程master_process.js的代碼:

// node/master_process.js
const { fork } = require('child_process')
const http = require('http')
const url = require('url')
const server = http.createServer((req, resp) => {
  const urlParsed = url.parse(req.url, true)

  if (urlParsed.pathname === '/hard_work') {
    // 對于hard_work請求我們啟動一個子進程來處理
    const child = fork('./child_process')
    // 告訴子進程開始工作
    child.send('START')
    // 接收子進程返回的數(shù)據(jù),并且返回給客戶端
    child.on('message', () => {
      resp.write('hard work')
      resp.end()
    })
  } else if (urlParsed.pathname === '/easy_work') {
    // 簡單工作都在主進程進行
    resp.write('easy work')
    resp.end()
  } else {
    resp.end()
  }
})
server.listen(8080, () => {
  console.log('server is up...')
})

在上面的代碼中對于/hard_work接口的請求,我們會通過fork函數(shù)開啟一個新的子進程來處理,當(dāng)子進程處理完畢我們拿到數(shù)據(jù)后就給客戶端返回結(jié)果。這里值得注意的是當(dāng)子進程完成任務(wù)后我沒有釋放子進程的資源,在實際項目里面我們也不應(yīng)該頻繁創(chuàng)建和銷毀子進程因為這個消耗也是很大的,更好的做法是使用進程池。下面是子進程(child_process.js)的實現(xiàn)邏輯:

// node/child_process.js

const hardWork = () => {
  // 100億次毫無意義的計算
  for (let i = 0; i < 10000000000; i++) {}
}
process.on('message', (message) => {
  if (message === 'START') {
    // 開始干活
    hardWork()
    // 干完活就通知子進程
    process.send(message)
  }
})

子進程的代碼也很簡單,它在啟動后會通過process.on的方式監(jiān)聽來自父進程的消息,在接收到開始命令后進行CPU密集型的計算,得出結(jié)果后返回給父進程。

運行上面master_process.js的代碼,我們可以發(fā)現(xiàn)即使調(diào)用了/hard_work接口,我們還是可以任意調(diào)用/easy_work接口并且馬上得到響應(yīng)的,此處沒有截圖,過程大家腦補一下就可以了。

除了fork函數(shù),child_process還提供了諸如execspawn等函數(shù)來啟動子進程,并且這些進程可以執(zhí)行任何的shell命令而不只是局限于Node腳本,有興趣的讀者后面可以通過官方文檔了解一下,這里就不過多介紹了。

Child Process的優(yōu)缺點

最后讓我們來總結(jié)一下Child Process的優(yōu)點有哪些:

  • 靈活:不只局限于Node進程,我們可以在子進程里面執(zhí)行任何的shell命令。這個其實是一個很大的優(yōu)點,假如我們的CPU密集型操作是用其它語言實現(xiàn)的(例如c語言處理圖像),而我們不想使用Node或者C++ Binding重新實現(xiàn)一遍的話我們就可以通過shell命令調(diào)用其它語言的程序,并且通過標(biāo)準輸入輸出和它們進行通信從而得到結(jié)果。
  • 細粒度的資源控制:不像Cluster Module,Child Process方案可以按照實際對CPU密集型計算的需求大小動態(tài)調(diào)整子進程的個數(shù),做到資源的細粒度控制,因此它理論上是可以解決Cluster Module解決不了的CPU密集型接口調(diào)用頻繁的問題。

不過Child Process的缺點也很明顯:

  • 資源消耗巨大:上面說它可以對資源進行細粒度控制的優(yōu)點時,也說了它只是理論上可以解決CPU密集型接口頻繁調(diào)用的問題,這是因為實際場景下我們的資源也是有限的,而每一個Child Process都是一個獨立的操作系統(tǒng)進程,會消耗巨大的資源。因此對于頻繁調(diào)用的接口我們需要采取能耗更低的方案也就是下面我會說的Worker Thread。
  • 進程通信麻煩:如果啟動的子進程也是Node應(yīng)用的話還好辦點,因為有內(nèi)置的API來和父進程通信,如果子進程不是Node應(yīng)用的話,我們只能通過標(biāo)準輸入輸出或者其它方式來進行進程間通信,這是一件很麻煩的事。

Worker Thread

無論是Cluster Module還是Child Process其實都是基于子進程的,它們都有一個巨大的缺點就是資源消耗大。為了解決這個問題Node從v10.5.0版本(v12.11.0 stable)開始就支持了worker_threads模塊,worker_thread是Node對于CPU密集型操作輕量級的線程解決方案。

概念介紹

Node的Worker Thread和其它語言的thread是一樣的,那就是并發(fā)地運行你的代碼。這里要注意是并發(fā)而不是并行并行只是意味著一段時間內(nèi)多件事情同時發(fā)生,而并發(fā)某個時間點多件事情同時發(fā)生。一個典型的并行例子就是React的Fiber架構(gòu),因為它是通過時分復(fù)用的方式來調(diào)度不同的任務(wù)來避免React渲染阻塞瀏覽器的其它行為的,所以本質(zhì)上它所有的操作還是在同一個操作系統(tǒng)線程執(zhí)行的。不過這里值得注意的是:雖然并發(fā)強調(diào)多個任務(wù)同時執(zhí)行,在單核CPU的情況下,并發(fā)會退化為并行。這是因為CPU同一個時刻只能做一件事,當(dāng)你有多個線程需要執(zhí)行的話就需要通過資源搶占的方式來時分復(fù)用執(zhí)行某些任務(wù)。不過這都是操作系統(tǒng)需要關(guān)心的東西,和我們沒什么關(guān)系了。

上面說了Node的Worker Thead和其他語言線程的thread類似的地方,接著我們來看一下它們不一樣的地方。如果你使用過其它語言的多線程編程方式,你會發(fā)現(xiàn)Node的多線程和它們很不一樣,因為Node多線程數(shù)據(jù)共享起來實在是太麻煩了!Node是不允許你通過共享內(nèi)存變量的方式來共享數(shù)據(jù)的,你只能用ArrayBuffer或者SharedArrayBuffer的方式來進行數(shù)據(jù)的傳遞和共享。雖然說這很不方便,不過這也讓我們不需要過多考慮多線程環(huán)境下數(shù)據(jù)安全等一系列問題,可以說有好處也有壞處吧。

接著我們來看一下如何使用Worker Thread來處理上面的CPU密集型任務(wù),

先看一下主線程(master_thread.js)的代碼:

// node/master_thread.js
const { Worker } = require('worker_threads')
const http = require('http')
const url = require('url')

const server = http.createServer((req, resp) => {
  const urlParsed = url.parse(req.url, true)

  if (urlParsed.pathname === '/hard_work') {
    // 對于每一個hard_work接口,我們都啟動一個子線程來處理
    const worker = new Worker('./child_process')
    // 告訴子線程開始任務(wù)
    worker.postMessage('START')
    worker.on('message', () => {
      // 在收到子線程回復(fù)后返回結(jié)果給客戶端
      resp.write('hard work')
      resp.end()
    })
  } else if (urlParsed.pathname === '/easy_work') {
    // 其它簡單操作都在主線程執(zhí)行
    resp.write('easy work')
    resp.end()
  } else {
    resp.end()
  }
})
server.listen(8080, () => {
  console.log('server is up...')
})

在上面的代碼中,我們的服務(wù)器每次接收到/hard_work請求都會通過new Worker的方式啟動一個Worker線程來處理,在worker處理完任務(wù)之后我們再將結(jié)果返回給客戶端,這個過程是異步的。接著再看一下子線程(worker_thead.js)的代碼實現(xiàn):

// node/worker_thread.js

const { parentPort } = require('worker_threads')

const hardWork = () => {
  // 100億次毫無意義的計算
  for (let i = 0; i < 10000000000; i++) {}
}
parentPort.on('message', (message) => {
  if (message === 'START') {
    hardWork()
    parentPort.postMessage()
  }
})

在上面的代碼中,worker thread在接收到主線程的命令后開始執(zhí)行CPU密集型操作,最后通過parentPort.postMessage的方式告知父線程任務(wù)已經(jīng)完成,從API上看父子線程通信還是挺方便的。

Worker Thread的優(yōu)缺點

最后我們還是總結(jié)一下Worker Thread的優(yōu)缺點。

首先我覺得它的優(yōu)點是:

  • 資源消耗小:不同于Cluster Module和Child Process基于進程的方式,Worker Thread是基于更加輕量級的線程的,所以它的資源開銷是相對較小的。不過麻雀雖小五臟俱全,每個Worker Thread都是有自己獨立的v8引擎實例事件循環(huán)系統(tǒng)的。這也就是說即使主線程卡死我們的Worker Thread也是可以繼續(xù)工作的,基于這個其實我們可以做很多有趣的事情。
  • 父子線程通信方便高效:和前面兩種方式不一樣,Worker Thread不需要通過IPC通信,所有數(shù)據(jù)都是在進程內(nèi)部實現(xiàn)共享和傳遞的。

不過Worker Thread也不是完美的:

  • 線程隔離性低:由于子線程不是在一個獨立的環(huán)境執(zhí)行的,所以某個子線程掛了還是會影響到其它線程,在這種情況下,你需要做一些額外的措施來保護其余線程不受影響。
  • 線程數(shù)據(jù)共享實現(xiàn)麻煩:和其它后端語言比起來,Node的數(shù)據(jù)共享還是比較麻煩的,不過這其實也避免了它需要考慮很多多線程下數(shù)據(jù)安全的問題。

總結(jié)

在本篇文章中我為大家介紹了Node為什么適合做I/O密集型應(yīng)用而很難處理CPU密集型任務(wù)的原因,并且為大家提供了三個可選方案來在實際開發(fā)中處理CPU密集型任務(wù)。每個方案其實都有利有弊,我們一定要根據(jù)實際情況進行選擇,永遠不要為了要用某個技術(shù)而一定要采取某個方案。

到此這篇關(guān)于Node處理CPU密集型任務(wù)有哪些方法的文章就介紹到這了,更多相關(guān)Node處理CPU密集內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Nodejs中使用phantom將html轉(zhuǎn)為pdf或圖片格式的方法

    Nodejs中使用phantom將html轉(zhuǎn)為pdf或圖片格式的方法

    這篇文章主要介紹了Nodejs中使用phantom將html轉(zhuǎn)為pdf或圖片格式的方法,需要的朋友可以參考下
    2017-09-09
  • 教你在heroku云平臺上部署Node.js應(yīng)用

    教你在heroku云平臺上部署Node.js應(yīng)用

    heroku是構(gòu)建在AWS之上的一個PaaS云平臺,現(xiàn)在支持Ruby, Node.js, Python, Java, 和 PHP,代碼的部署是通過git進行,編譯和運行都是自動的。
    2014-07-07
  • node.js+Ajax實現(xiàn)獲取HTTP服務(wù)器返回數(shù)據(jù)

    node.js+Ajax實現(xiàn)獲取HTTP服務(wù)器返回數(shù)據(jù)

    這篇文章主要介紹了node.js+Ajax實現(xiàn)獲取HTTP服務(wù)器返回數(shù)據(jù),講解的十分詳細,也給出了很多的實例,是篇非常不錯的文章,這里推薦給大家。
    2014-11-11
  • 詳解nodejs http請求相關(guān)總結(jié)

    詳解nodejs http請求相關(guān)總結(jié)

    這篇文章主要介紹了nodejs http請求相關(guān)總結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • Node.js的cross-env工具包使用介紹

    Node.js的cross-env工具包使用介紹

    這篇文章主要為大家介紹了Node.js的cross-env工具包使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • 在Nodejs中實現(xiàn)一個緩存系統(tǒng)的方法詳解

    在Nodejs中實現(xiàn)一個緩存系統(tǒng)的方法詳解

    在數(shù)據(jù)庫查詢遇到瓶頸時,我們通??梢圆捎镁彺鎭硖嵘樵兯俣?同時緩解數(shù)據(jù)庫壓力,在一些簡單場景中,我們也可以自己實現(xiàn)一個緩存系統(tǒng),避免使用額外的緩存中間件,這篇文章將帶你一步步實現(xiàn)一個完善的緩存系統(tǒng),需要的朋友可以參考下
    2024-03-03
  • yarn?install命令報錯warning?package-lock.json?found解決辦法

    yarn?install命令報錯warning?package-lock.json?found解決辦法

    這篇文章主要給大家介紹了關(guān)于yarn?install命令報錯warning?package-lock.json?found的解決辦法,文中通過圖文將解決的辦法介紹的非常詳細,還分享了更多yarn install遇到的報錯及解決方案,需要的朋友可以參考下
    2024-02-02
  • node.js中的http.response.getHeader方法使用說明

    node.js中的http.response.getHeader方法使用說明

    這篇文章主要介紹了node.js中的http.response.getHeader方法使用說明,本文介紹了http.response.getHeader的方法說明、語法、接收參數(shù)、使用實例和實現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • npm安裝慢的問題分析及解決方法

    npm安裝慢的問題分析及解決方法

    在Node.js開發(fā)過程中,npm install 是安裝和管理項目依賴的關(guān)鍵命令,然而,有時我們會遇到 npm install 運行卡住不動的情況,所以本文給大家介紹了npm安裝慢的問題分析及解決方法,需要的朋友可以參考下
    2025-03-03
  • Node.js的項目構(gòu)建工具Grunt的安裝與配置教程

    Node.js的項目構(gòu)建工具Grunt的安裝與配置教程

    Grunt是為Node打造的項目構(gòu)建工具,相當(dāng)于C/C++世界中的makefile,可以執(zhí)行像壓縮、編譯、單元測試、代碼檢查以及打包發(fā)布的任務(wù),下面我們就來一起看一下Node.js的項目構(gòu)建工具Grunt的安裝與配置教程:
    2016-05-05

最新評論

边坝县| 曲水县| 宁南县| 西丰县| 梁山县| 泰兴市| 成安县| 小金县| 泸定县| 新巴尔虎右旗| 宁津县| 明水县| 米脂县| 滦平县| 古蔺县| 松阳县| 维西| 苍梧县| 黑河市| 宜州市| 屯留县| 衡东县| 柯坪县| 苏尼特右旗| 安义县| 施秉县| 应用必备| 炎陵县| 吉隆县| 连云港市| 六盘水市| 海兴县| 齐齐哈尔市| 罗定市| 罗平县| 和硕县| 陵水| 邢台县| 中阳县| 辉南县| 海林市|