欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Node.js中使用事件發(fā)射器模式實(shí)現(xiàn)事件綁定詳解

 更新時(shí)間:2014年08月15日 12:08:00   作者:Jack Yao''s Workshop  
這篇文章主要介紹了Node.js中使用事件發(fā)射器模式實(shí)現(xiàn)事件綁定詳解,本文一并講解了回調(diào)模式、發(fā)射器模式、事件類型等基礎(chǔ)知識(shí)做了補(bǔ)充,需要的朋友可以參考下

在Node里,很多對(duì)象都會(huì)發(fā)射事件。比如,一個(gè)TCP服務(wù)器,每當(dāng)有客戶端請(qǐng)求連接就會(huì)發(fā)射“connect”事件,又比如,每當(dāng)讀取一整塊數(shù)據(jù),文件系統(tǒng)就會(huì)發(fā)射一個(gè)“data”事件。這些對(duì)象在Node里被稱為事件發(fā)射器(event emitter)。事件發(fā)射器允許程序員訂閱他們感興趣的事件,并將回調(diào)函數(shù)綁定到相關(guān)的事件上,這樣每當(dāng)事件發(fā)射器發(fā)射事件時(shí)回調(diào)函數(shù)就會(huì)被調(diào)用。發(fā)布/訂閱模式非常類似傳統(tǒng)的GUI模式,比如按鈕被點(diǎn)擊時(shí)程序就會(huì)收到相應(yīng)的通知。使用這種模式,服務(wù)端程序可以在一些事件發(fā)生時(shí)作出反應(yīng),比如有客戶端連接,socket上有可用數(shù)據(jù),或者文件被關(guān)閉的時(shí)候。

還可以創(chuàng)建自己的事件發(fā)射器,事實(shí)上,Node專門提供了一個(gè)EventEmitter偽類,可以把它當(dāng)作基類來創(chuàng)建自己的事件發(fā)射器。

理解回調(diào)模式

異步編程不使用函數(shù)返回值來表明函數(shù)調(diào)用的結(jié)束,而是采用后繼傳遞風(fēng)格。

“后繼傳遞風(fēng)格”(CPS:Continuation-passing style)是一種編程風(fēng)格,流程控制被顯式傳遞給下一步操作……

CPS風(fēng)格的函數(shù)會(huì)接受一個(gè)函數(shù)作為額外參數(shù),這個(gè)函數(shù)用來顯式指出程序控制的下個(gè)流程,當(dāng)CPS函數(shù)計(jì)算出它的“返回值”,它就會(huì)調(diào)用那個(gè)代表了程序下個(gè)流程的函數(shù),并將CPS函數(shù)的“返回值”作為其參數(shù)。

出自維基百科——http://en.wikipedia.org/wiki/Continuation-passing_style

這種編程風(fēng)格里,每個(gè)函數(shù)在執(zhí)行結(jié)束后都會(huì)調(diào)用一個(gè)回調(diào)函數(shù),這樣程序就可以繼續(xù)運(yùn)行。后面你會(huì)明白,JavaScript非常適合這種編程風(fēng)格,下面是個(gè)Node下將文件加載到內(nèi)存的例子:

復(fù)制代碼 代碼如下:

var fs = require('fs');

fs.readFile('/etc/passwd', function(err, fileContent) {

    if (err) {

        throw err;

    }

    console.log('file content', fileContent.toString());

});

這個(gè)例子里,你傳遞了一個(gè)內(nèi)聯(lián)匿名函數(shù)作為fs.readFile的第二個(gè)參數(shù),其實(shí)這就是在使用CPS編程,因?yàn)槟惆殉绦驁?zhí)行的后續(xù)流程交給了那個(gè)回調(diào)函數(shù)。

如你所見,回調(diào)函數(shù)的第一個(gè)參數(shù)是個(gè)錯(cuò)誤對(duì)象,如果程序發(fā)生錯(cuò)誤,這個(gè)參數(shù)將會(huì)是一個(gè)Error類的實(shí)例,這是Node里CPS編程的一個(gè)常見模式。

理解事件發(fā)射器模式

標(biāo)準(zhǔn)回調(diào)模式里,把一個(gè)函數(shù)作為參數(shù)傳遞給將被執(zhí)行的函數(shù),這種模式在客戶端需要在函數(shù)完成后被通知的場(chǎng)景下工作的很好。但是如果函數(shù)的執(zhí)行過程中發(fā)生了多個(gè)事件或事件重復(fù)發(fā)生了多次,這種模式就不太適合了。比如,你想在socket每次收到可用數(shù)據(jù)時(shí)得到通知,這種場(chǎng)景你會(huì)發(fā)現(xiàn)標(biāo)準(zhǔn)回調(diào)模式不太好用,這時(shí)事件發(fā)射器模式就派上用場(chǎng)了,你可以用一套標(biāo)準(zhǔn)接口來清晰的分離事件發(fā)生器和事件監(jiān)聽器。

使用事件發(fā)生器模式時(shí),會(huì)涉及到兩個(gè)或多個(gè)對(duì)象——事件發(fā)射器和一個(gè)或多個(gè)事件監(jiān)聽器。

事件發(fā)射器,顧名思義,是個(gè)可以產(chǎn)生事件的對(duì)象。而事件監(jiān)聽器則是綁定到事件發(fā)射器上的代碼,用來監(jiān)聽特定類型的事件,就像下面的例子:

復(fù)制代碼 代碼如下:

var req = http.request(options, function(response) {

    response.on("data", function(data) {

        console.log("some data from the response", data);

    });

    response.on("end", function() {

         console.log("response ended");

    });

});

req.end();

這段代碼演示了用Node的 http.request API(見后面章節(jié))創(chuàng)建一個(gè)HTTP請(qǐng)求來訪問遠(yuǎn)程HTTP服務(wù)器時(shí)的兩個(gè)必要步驟。第一行采用了“后繼傳遞風(fēng)格”(CPS:Continuation-passing style),傳遞了一個(gè)當(dāng)HTTP響應(yīng)時(shí)會(huì)被調(diào)用的內(nèi)聯(lián)函數(shù)。HTTP請(qǐng)求API在這兒使用CPS是因?yàn)槌绦蛐枰趆ttp.request函數(shù)執(zhí)行完畢后才繼續(xù)執(zhí)行后續(xù)操作。

當(dāng)http.request執(zhí)行完畢,就會(huì)調(diào)用那個(gè)匿名回調(diào)函數(shù),然后將HTTP響應(yīng)對(duì)象作為參數(shù)傳遞給它,這個(gè)HTTP響應(yīng)對(duì)象是個(gè)事件發(fā)射器,根據(jù)Node文檔,它可以發(fā)射包括data,end在內(nèi)的很多事件,你注冊(cè)的那些回調(diào)函數(shù)會(huì)在每次事件發(fā)生時(shí)被調(diào)用。

作為一條經(jīng)驗(yàn),當(dāng)你需要在請(qǐng)求的操作完成后重新獲取執(zhí)行權(quán)時(shí)使用CPS模式,以及當(dāng)事件可以發(fā)生多次時(shí)使用事件發(fā)射器模式。

理解事件類型

被發(fā)射的事件都有一個(gè)用字符串表示的類型,前面的例子包含“data”和“end”兩個(gè)事件類型,它們是由事件發(fā)射器來定義的任意字符串,不過約定俗成的是,事件類型通常都由不包含空字符的小寫單詞組成。

不能用代碼來推斷出事件發(fā)射器能產(chǎn)生哪些類型的事件,因?yàn)槭录l(fā)射器API并沒有內(nèi)省機(jī)制,因此你使用的API應(yīng)該有文檔來表明它能發(fā)射那些類型的事件。

一旦事件發(fā)生,事件發(fā)射器就會(huì)調(diào)用跟事件相關(guān)的監(jiān)聽器,并將相關(guān)數(shù)據(jù)作為參數(shù)傳遞給監(jiān)聽器。在前面http.request那個(gè)例子里,“data”事件回調(diào)函數(shù)接受一個(gè)data對(duì)象作為它第一個(gè)也是唯一的參數(shù),而“end”不接受任何數(shù)據(jù),這些參數(shù)作為API契約的一部分也是由API的作者主觀定義的,這些回調(diào)函數(shù)的參數(shù)簽名也會(huì)在每個(gè)事件發(fā)射器的API文檔里有說明。

事件發(fā)射器雖然是個(gè)為所有類型事件服務(wù)的接口,不過“error”事件是Node里的一個(gè)特殊實(shí)現(xiàn)。Node里的大多數(shù)事件發(fā)射器都會(huì)在程序發(fā)生錯(cuò)誤時(shí)產(chǎn)生“error”事件,如果程序沒有監(jiān)聽某個(gè)事件發(fā)射器的 “error”事件,事件發(fā)射器將會(huì)注意到并在錯(cuò)誤發(fā)生時(shí)向上拋出一個(gè)未捕獲異常。

你可以在Node PERL里運(yùn)行下面的代碼來測(cè)試下效果,它模擬了一個(gè)能產(chǎn)生兩種事件的事件發(fā)射器:

復(fù)制代碼 代碼如下:

var em = new (require('events').EventEmitter)();

em.emit('event1');

em.emit('error', new Error('My mistake'));

你將會(huì)看到下面的輸出:

復(fù)制代碼 代碼如下:

var em = new (require('events').EventEmitter)();

undefined

> em.emit('event1');

false

> em.emit('error', new Error('My mistake'));

Error: My mistake

at repl:1:18

at REPLServer.eval (repl.js:80:21)

at repl.js:190:20

at REPLServer.eval (repl.js:87:5)

at Interface.<anonymous> (repl.js:182:12)

at Interface.emit (events.js:67:17)

at Interface._onLine (readline.js:162:10)

at Interface._line (readline.js:426:8)

at Interface._ttyWrite (readline.js:603:14)

at ReadStream.<anonymous> (readline.js:82:12)

>

代碼第2行,隨便發(fā)射了一個(gè)叫“event1”的事件,沒有任何效果,但是當(dāng)發(fā)射“error”事件時(shí),錯(cuò)誤被拋出到堆棧。如果程序不是運(yùn)行在PERL命令行環(huán)境里,程序?qū)?huì)因?yàn)槲床东@的異常而崩潰。

使用事件發(fā)射器API

任何實(shí)現(xiàn)了事件發(fā)射器模式的對(duì)象(比如TCP Socket,HTTP 請(qǐng)求等)都實(shí)現(xiàn)了下面的一組方法:

復(fù)制代碼 代碼如下:

.addListener和.on —— 為指定類型的事件添加事件監(jiān)聽器
.once —— 為指定類型的事件綁定一個(gè)僅執(zhí)行一次的事件監(jiān)聽器
.removeEventListener —— 刪除綁定到指定事件上的某個(gè)監(jiān)聽器
.removeAllEventListener —— 刪除綁定到指定事件上的所有監(jiān)聽器

下面我們具體介紹它們。

使用.addListener()或.on()綁定回調(diào)函數(shù)

通過指定事件類型和回調(diào)函數(shù),你可以注冊(cè)當(dāng)事件發(fā)生時(shí)被執(zhí)行的操作。比如,文件讀取數(shù)據(jù)流時(shí)如果有可用的數(shù)據(jù)塊,就會(huì)發(fā)射一個(gè)“data”事件,下面代碼展示如何通過傳入一個(gè)回調(diào)函數(shù)來讓程序告訴你發(fā)生了data事件。

復(fù)制代碼 代碼如下:

function receiveData(data) {

   console.log("got data from file read stream: %j", data);

}

readStream.addListener(“data”, receiveData);

你也可以使用.on,它只是.addListener的簡(jiǎn)寫方式,下面的代碼和上面的是一樣的:

復(fù)制代碼 代碼如下:

function receiveData(data) {

   console.log("got data from file read stream: %j", data);

}
readStream.on(“data”, receiveData);

前面代碼,使用事先定義的一個(gè)的命名函數(shù)作為回調(diào)函數(shù),你也可以使用一個(gè)內(nèi)聯(lián)匿名函數(shù)來簡(jiǎn)化代碼:

復(fù)制代碼 代碼如下:

readStream.on("data", function(data) {

   console.log("got data from file read stream: %j", data);

});


前面說過,傳遞給回調(diào)函數(shù)的參數(shù)個(gè)數(shù)和簽名依賴于具體的事件發(fā)射器對(duì)象和事件類型,它們并不是被標(biāo)準(zhǔn)化的,“data”事件可能傳遞的是一個(gè)數(shù)據(jù)緩沖對(duì)象,“error”事件傳遞一個(gè)錯(cuò)誤對(duì)象,數(shù)據(jù)流的“end”事件不向事件監(jiān)聽器傳遞任何數(shù)據(jù)。

綁定多個(gè)事件監(jiān)聽器

事件發(fā)射器模式允許多個(gè)事件監(jiān)聽器監(jiān)聽同一個(gè)事件發(fā)射器的同一事件類型,比如:

復(fù)制代碼 代碼如下:

I have some data here.

I have some data here too.

事件發(fā)射器負(fù)責(zé)按監(jiān)聽器的注冊(cè)順序調(diào)用指定事件類型上綁定的所有監(jiān)聽器,也就是說:

1.當(dāng)事件發(fā)生后事件監(jiān)聽器可能不會(huì)被立刻調(diào)用,也許會(huì)有其它事件監(jiān)聽器在它之前被調(diào)用。
2.異常被拋出到堆棧是不正常的行為,可能是因?yàn)榇a里有bug,當(dāng)事件被發(fā)射時(shí),如果有一個(gè)事件監(jiān)聽器在被調(diào)用時(shí)拋出了異常,可能會(huì)導(dǎo)致一些事件監(jiān)聽器永遠(yuǎn)不會(huì)被調(diào)用。這種情況下,事件發(fā)射器會(huì)捕獲到異常,也許還會(huì)處理它。

看下面這個(gè)例子:

復(fù)制代碼 代碼如下:

readStream.on("data", function(data) {

   throw new Error("Something wrong has happened");

});

readStream.on("data", function(data) {

   console.log('I have some data here too.');

});

因?yàn)榈谝粋€(gè)監(jiān)聽器拋出了異常,因此第二個(gè)監(jiān)聽器不會(huì)被調(diào)用。

用.removeListener()從事件發(fā)射器移除一個(gè)事件監(jiān)聽器

如果當(dāng)你不再關(guān)心一個(gè)對(duì)象的某個(gè)事件時(shí),你可以通過指定事件類型和回調(diào)函數(shù)來取消已注冊(cè)的事件監(jiān)聽器,像這樣:

復(fù)制代碼 代碼如下:

function receiveData(data) {

    console.log("got data from file read stream: %j", data);

}

readStream.on("data", receiveData);

// ...

readStream.removeListener("data", receiveData);

這個(gè)例子里,最后一行把一個(gè)可能在將來被隨時(shí)調(diào)用的事件監(jiān)聽器從事件發(fā)射器對(duì)象移除了。

為了刪除監(jiān)聽器,你必須給回調(diào)函數(shù)命名,因?yàn)樵谔砑雍蛣h除的時(shí)候需要回調(diào)函數(shù)的名字。

使用.once()讓回調(diào)函數(shù)最多執(zhí)行一次

如果你想監(jiān)聽一個(gè)最多執(zhí)行一次的事件,或者只對(duì)某個(gè)事件發(fā)生的第一次感興趣,可以用.once()函數(shù):

復(fù)制代碼 代碼如下:

function receiveData(data) {

    console.log("got data from file read stream: %j", data);

}

readStream.once("data", receiveData);

上面的代碼,receiveData函數(shù)只會(huì)被調(diào)用一次。如果readStream對(duì)象發(fā)射了data事件,receiveData回調(diào)函數(shù)將會(huì)而且僅會(huì)被觸發(fā)一次。

它其實(shí)只是個(gè)方便方法,因?yàn)楹芎?jiǎn)單的就能實(shí)現(xiàn)它,像這樣:

復(fù)制代碼 代碼如下:

var EventEmitter = require("events").EventEmitter;

EventEmitter.prototype.once = function(type, callback) {

   var that = this;

   this.on(type, function listener() {

      that.removeListener(type, listener);

      callback.apply(that, arguments);

   });

};

上面代碼里,你重新定了EventEmitter.prototype.once函數(shù),同時(shí)也重定義了每個(gè)繼承自EventEmitter的所有對(duì)象的once函數(shù)。代碼只是簡(jiǎn)單的使用.on()方法,一旦收到了事件,就用.removeEventListener()取消回調(diào)函數(shù)的注冊(cè),并調(diào)用原來的回調(diào)函數(shù)。

注意:前面代碼里使用了function.apply()方法,它接受一個(gè)對(duì)象并把它作為內(nèi)含的this變量,以及一個(gè)參數(shù)數(shù)組。前面例子里,通過事件發(fā)射器把未修改過的參數(shù)數(shù)組透明地傳遞給回調(diào)函數(shù)。

用.removeAllListeners()從事件發(fā)射器移除所有事件監(jiān)聽器

你可以像下面那樣從事件發(fā)射器移除所有注冊(cè)到指定事件類型上的所有監(jiān)聽器:

復(fù)制代碼 代碼如下:

emitter.removeAllListeners(type);

比如,你可以這樣取消所有進(jìn)程中斷信號(hào)的監(jiān)聽器:

復(fù)制代碼 代碼如下:

process.removeAllListeners("SIGTERM");

注意:作為一條經(jīng)驗(yàn),推薦你只在確切知道刪除了什么內(nèi)容時(shí)才使用這個(gè)函數(shù),否則,應(yīng)該讓應(yīng)用程序其它部分來刪除事件監(jiān)聽器集合,或者也可以讓程序的那些部分自己負(fù)責(zé)移除監(jiān)聽器。但不管怎樣,在某些罕見的場(chǎng)景下,這個(gè)函數(shù)還是很有用的,比如當(dāng)你準(zhǔn)備有序的關(guān)閉一個(gè)事件發(fā)射器或者關(guān)閉整個(gè)進(jìn)程的時(shí)候。

創(chuàng)建事件發(fā)射器

事件發(fā)射器用一個(gè)很棒的方式讓編程接口變得更通用,在一個(gè)常見易懂的編程模式里,客戶端直接調(diào)用各種函數(shù),而在事件發(fā)射器模式中,客戶端被綁定到各種事件上,這會(huì)讓你的程序變得更靈活。(譯者注:這句不太自信,貼出原文:The event emitter provides a great way of making a programming interface more generic. When you use a common understood pattern, clients bind to events instead of invoking functions, making your program more flexible.)

此外,通過使用事件發(fā)射器,你還可以獲得許多特性,比如在同一事件上綁定多個(gè)互不相關(guān)的監(jiān)聽器。

從Node事件發(fā)射器繼承

如果你對(duì)Node的事件發(fā)射器模式感興趣,并打算用到自己的應(yīng)用程序里,你可以通過繼承EventEmitter來創(chuàng)建一個(gè)偽類:

復(fù)制代碼 代碼如下:

util = require('util');

var EventEmitter = require('events').EventEmitter;

// 這是MyClass的構(gòu)造函數(shù):

var MyClass = function() {

}

util.inherits(MyClass, EventEmitter);

注意:util.inherits建立了MyClass的原形鏈,讓你的MyClass實(shí)例可以使用EventEmitter的原形方法。

發(fā)射事件

通過繼承自EventEmitter,MyClass可以像這樣發(fā)射事件了:

復(fù)制代碼 代碼如下:

MyClass.prototype.someMethod = function() {

    this.emit("custom event", "argument 1", "argument 2");

};

上面的代碼,當(dāng)someMethond方法被MyClass的實(shí)例調(diào)用時(shí),就會(huì)發(fā)射一個(gè)叫“cuteom event”的事件,這個(gè)事件還會(huì)發(fā)射兩個(gè)字符串作為數(shù)據(jù):“argument 1”和“argument 2”,它們將會(huì)作為參數(shù)傳遞給事件監(jiān)聽器。

MyClass實(shí)例的客戶端可以像這樣監(jiān)聽“custom event”事件:

復(fù)制代碼 代碼如下:

var myInstance = new MyClass();

myInstance.on('custom event', function(str1, str2) {

    console.log('got a custom event with the str1 %s and str2 %s!', str1, str2);

});

再比如,你可以這樣創(chuàng)建一個(gè)每秒發(fā)射一次“tick”事件的Ticker類:

復(fù)制代碼 代碼如下:

var util = require('util'),

EventEmitter = require('events').EventEmitter;

var Ticker = function() {

    var self = this;

    setInterval(function() {

        self.emit('tick');

    }, 1000);

};

util.inherits(Ticker, EventEmitter);

用Ticker類的客戶端可以展示如何使用Ticker類和監(jiān)聽“tick”事件,

復(fù)制代碼 代碼如下:

var ticker = new Ticker();

ticker.on("tick", function() {

    console.log("tick");

});

小結(jié)

事件發(fā)射器模式是種可重入模式(recurrent pattern),可以用它將事件發(fā)射器對(duì)象從一組特定事件的代碼中解耦合。

可以用event_emitter.on()來為特定類型的事件注冊(cè)監(jiān)聽器,并用event_emitter.removeListener()來取消注冊(cè)。

還可以通過繼承EventEmitter和簡(jiǎn)單的使用.emit()函數(shù)來創(chuàng)建自己的事件發(fā)射器。

相關(guān)文章

  • 詳解如何修改 node_modules 里的文件

    詳解如何修改 node_modules 里的文件

    這篇文章主要介紹了詳解如何修改node_modules里的文件,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • node+axios實(shí)現(xiàn)服務(wù)端文件上傳示例

    node+axios實(shí)現(xiàn)服務(wù)端文件上傳示例

    這篇文章主要介紹了node+axios實(shí)現(xiàn)服務(wù)端文件上傳示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Node發(fā)出HTTP POST請(qǐng)求的方法實(shí)例小結(jié)

    Node發(fā)出HTTP POST請(qǐng)求的方法實(shí)例小結(jié)

    這篇文章主要介紹了Node發(fā)出HTTP POST請(qǐng)求的方法,結(jié)合實(shí)例形式總結(jié)分析了三種常用的post請(qǐng)求操作方法,以及相關(guān)庫操作注意事項(xiàng),需要的朋友可以參考下
    2023-05-05
  • Nodejs連接mysql并實(shí)現(xiàn)增、刪、改、查操作的方法詳解

    Nodejs連接mysql并實(shí)現(xiàn)增、刪、改、查操作的方法詳解

    這篇文章主要介紹了Nodejs連接mysql并實(shí)現(xiàn)增、刪、改、查操作的方法,結(jié)合實(shí)例形式詳細(xì)分析了nodejs針對(duì)mysql數(shù)據(jù)庫的的連接、mysql數(shù)據(jù)庫的創(chuàng)建及nodejs針對(duì)mysql增刪改查等相關(guān)操作具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2018-01-01
  • 在nodejs中使用swagger方式

    在nodejs中使用swagger方式

    這篇文章主要介紹了在nodejs中使用swagger方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Node.js項(xiàng)目中調(diào)用JavaScript的EJS模板庫的方法

    Node.js項(xiàng)目中調(diào)用JavaScript的EJS模板庫的方法

    這篇文章主要介紹了Node.js項(xiàng)目中調(diào)用JavaScript的EJS模板庫的方法,通過EJS模板引擎可以制作出維護(hù)性良好的HTML代碼結(jié)構(gòu),需要的朋友可以參考下
    2016-03-03
  • export?default?和?export?的使用方式示例詳解

    export?default?和?export?的使用方式示例詳解

    這篇文章主要介紹了export?default?和?export?的使用方式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • node ftp上傳文件夾到服務(wù)器案例詳解

    node ftp上傳文件夾到服務(wù)器案例詳解

    這篇文章主要介紹了node ftp上傳文件夾到服務(wù)器的視線方法,結(jié)合具體實(shí)例分析了node.js調(diào)用ftp模塊進(jìn)行文件上傳的相關(guān)配置、連接、path路徑操作與文件傳輸實(shí)現(xiàn)方法,需要的朋友可以參考下
    2023-04-04
  • NodeJS連接MySQL數(shù)據(jù)庫并進(jìn)行增刪改查操作詳解

    NodeJS連接MySQL數(shù)據(jù)庫并進(jìn)行增刪改查操作詳解

    本篇是使用NodeJS的模塊MySQL操作MySQL數(shù)據(jù)庫的基礎(chǔ)教程,連接MySQL數(shù)據(jù)庫并進(jìn)行增刪改查操作詳解,需要的朋友可以參考下
    2024-02-02
  • npm?install安裝過程報(bào)錯(cuò)的實(shí)用解決辦法

    npm?install安裝過程報(bào)錯(cuò)的實(shí)用解決辦法

    最近做項(xiàng)目遇到npm install 的問題,下面這篇文章主要給大家介紹了關(guān)于npm?install安裝過程報(bào)錯(cuò)的實(shí)用解決辦法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06

最新評(píng)論