激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務(wù)器之家 - 編程語(yǔ)言 - JavaScript - node.js - nodejs中的異步編程知識(shí)點(diǎn)詳解

nodejs中的異步編程知識(shí)點(diǎn)詳解

2022-01-04 16:20flydean node.js

在本篇內(nèi)容里小編給大家整理的是一篇關(guān)于nodejs中的異步編程知識(shí)點(diǎn)詳解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。

簡(jiǎn)介

因?yàn)閖avascript默認(rèn)情況下是單線程的,這意味著代碼不能創(chuàng)建新的線程來(lái)并行執(zhí)行。但是對(duì)于最開(kāi)始在瀏覽器中運(yùn)行的javascript來(lái)說(shuō),單線程的同步執(zhí)行環(huán)境顯然無(wú)法滿足頁(yè)面點(diǎn)擊,鼠標(biāo)移動(dòng)這些響應(yīng)用戶的功能。于是瀏覽器實(shí)現(xiàn)了一組API,可以讓javascript以回調(diào)的方式來(lái)異步響應(yīng)頁(yè)面的請(qǐng)求事件。

更進(jìn)一步,nodejs引入了非阻塞的 I/O ,從而將異步的概念擴(kuò)展到了文件訪問(wèn)、網(wǎng)絡(luò)調(diào)用等。

今天,我們將會(huì)深入的探討一下各種異步編程的優(yōu)缺點(diǎn)和發(fā)展趨勢(shì)。

同步異步和阻塞非阻塞

在討論nodejs的異步編程之前,讓我們來(lái)討論一個(gè)比較容易混淆的概念,那就是同步,異步,阻塞和非阻塞。

所謂阻塞和非阻塞是指進(jìn)程或者線程在進(jìn)行操作或者數(shù)據(jù)讀寫(xiě)的時(shí)候,是否需要等待,在等待的過(guò)程中能否進(jìn)行其他的操作。

如果需要等待,并且等待過(guò)程中線程或進(jìn)程無(wú)法進(jìn)行其他操作,只能傻傻的等待,那么我們就說(shuō)這個(gè)操作是阻塞的。

反之,如果進(jìn)程或者線程在進(jìn)行操作或者數(shù)據(jù)讀寫(xiě)的過(guò)程中,還可以進(jìn)行其他的操作,那么我們就說(shuō)這個(gè)操作是非阻塞的。

同步和異步,是指訪問(wèn)數(shù)據(jù)的方式,同步是指需要主動(dòng)讀取數(shù)據(jù),這個(gè)讀取過(guò)程可能是阻塞或者是非阻塞的。而異步是指并不需要主動(dòng)去讀取數(shù)據(jù),是被動(dòng)的通知。

很明顯,javascript中的回調(diào)是一個(gè)被動(dòng)的通知,我們可以稱(chēng)之為異步調(diào)用。

javascript中的回調(diào)

javascript中的回調(diào)是異步編程的一個(gè)非常典型的例子:

?
1
2
3
document.getElementById('button').addEventListener('click', () => {
 console.log('button clicked!');
})

上面的代碼中,我們?yōu)閎utton添加了一個(gè)click事件監(jiān)聽(tīng)器,如果監(jiān)聽(tīng)到了click事件,則會(huì)出發(fā)回調(diào)函數(shù),輸出相應(yīng)的信息。

回調(diào)函數(shù)就是一個(gè)普通的函數(shù),只不過(guò)它被作為參數(shù)傳遞給了addEventListener,并且只有事件觸發(fā)的時(shí)候才會(huì)被調(diào)用。

上篇文章我們講到的setTimeout和setInterval實(shí)際上都是異步的回調(diào)函數(shù)。

回調(diào)函數(shù)的錯(cuò)誤處理

在nodejs中怎么處理回調(diào)的錯(cuò)誤信息呢?nodejs采用了一個(gè)非常巧妙的辦法,在nodejs中,任何回調(diào)函數(shù)中的第一個(gè)參數(shù)為錯(cuò)誤對(duì)象,我們可以通過(guò)判斷這個(gè)錯(cuò)誤對(duì)象的存在與否,來(lái)進(jìn)行相應(yīng)的錯(cuò)誤處理。

?
1
2
3
4
5
6
7
8
9
10
fs.readFile('/文件.json', (err, data) => {
 if (err !== null) {
 //處理錯(cuò)誤
 console.log(err)
 return
 }
 
 //沒(méi)有錯(cuò)誤,則處理數(shù)據(jù)。
 console.log(data)
})

回調(diào)地獄

javascript的回調(diào)雖然非常的優(yōu)秀,它有效的解決了同步處理的問(wèn)題。但是遺憾的是,如果我們需要依賴回調(diào)函數(shù)的返回值來(lái)進(jìn)行下一步的操作的時(shí)候,就會(huì)陷入這個(gè)回調(diào)地獄。

叫回調(diào)地獄有點(diǎn)夸張了,但是也是從一方面反映了回調(diào)函數(shù)所存在的問(wèn)題。

?
1
2
3
4
5
6
7
fs.readFile('/a.json', (err, data) => {
 if (err !== null) {
 fs.readFile('/b.json',(err,data) =>{
  //callback inside callback
 })
 }
})

怎么解決呢?

別怕ES6引入了Promise,ES2017引入了Async/Await都可以解決這個(gè)問(wèn)題。

ES6中的Promise

什么是Promise

Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案“回調(diào)函數(shù)和事件”更合理和更強(qiáng)大。

所謂Promise,簡(jiǎn)單說(shuō)就是一個(gè)容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。

從語(yǔ)法上說(shuō),Promise 是一個(gè)對(duì)象,從它可以獲取異步操作的消息。

Promise的特點(diǎn)

Promise有兩個(gè)特點(diǎn):

1、對(duì)象的狀態(tài)不受外界影響。

Promise對(duì)象代表一個(gè)異步操作,有三種狀態(tài):Pending(進(jìn)行中)、Resolved(已完成,又稱(chēng) Fulfilled)和Rejected(已失敗)。

只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無(wú)法改變這個(gè)狀態(tài)。

2、一旦狀態(tài)改變,就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果。

Promise對(duì)象的狀態(tài)改變,只有兩種可能:從Pending變?yōu)镽esolved和從Pending變?yōu)镽ejected。

這與事件(Event)完全不同,事件的特點(diǎn)是,如果你錯(cuò)過(guò)了它,再去監(jiān)聽(tīng),是得不到結(jié)果的。

Promise的優(yōu)點(diǎn)

  1. Promise將異步操作以同步操作的流程表達(dá)出來(lái),避免了層層嵌套的回調(diào)函數(shù)。
  2. Promise對(duì)象提供統(tǒng)一的接口,使得控制異步操作更加容易。

Promise的缺點(diǎn)

  1. 無(wú)法取消Promise,一旦新建它就會(huì)立即執(zhí)行,無(wú)法中途取消。
  2. 如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯(cuò)誤,不會(huì)反應(yīng)到外部。
  3. 當(dāng)處于Pending狀態(tài)時(shí),無(wú)法得知目前進(jìn)展到哪一個(gè)階段(剛剛開(kāi)始還是即將完成)。

Promise的用法

Promise對(duì)象是一個(gè)構(gòu)造函數(shù),用來(lái)生成Promise實(shí)例:

?
1
2
3
4
5
6
7
var promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 異步操作成功 */){
resolve(value);
} else { reject(error); }
}
);

promise可以接then操作,then操作可以接兩個(gè)function參數(shù),第一個(gè)function的參數(shù)就是構(gòu)建Promise的時(shí)候resolve的value,第二個(gè)function的參數(shù)就是構(gòu)建Promise的reject的error。

?
1
2
3
4
5
promise.then(function(value) {
// success
}, function(error) {
// failure }
);

我們看一個(gè)具體的例子:

?
1
2
3
4
5
6
7
function timeout(ms){
 return new Promise(((resolve, reject) => {
  setTimeout(resolve,ms,'done');
 }))
}
 
timeout(100).then(value => console.log(value));

Promise中調(diào)用了一個(gè)setTimeout方法,并會(huì)定時(shí)觸發(fā)resolve方法,并傳入?yún)?shù)done。

最后程序輸出done。

Promise的執(zhí)行順序

Promise一經(jīng)創(chuàng)建就會(huì)立馬執(zhí)行。但是Promise.then中的方法,則會(huì)等到一個(gè)調(diào)用周期過(guò)后再次調(diào)用,我們看下面的例子:

?
1
2
3
4
5
6
7
8
9
10
let promise = new Promise(((resolve, reject) => {
 console.log('Step1');
 resolve();
}));
 
promise.then(() => {
 console.log('Step3');
});
 
console.log('Step2');

輸出

Step1
Step2
Step3

async和await

Promise當(dāng)然很好,我們將回調(diào)地獄轉(zhuǎn)換成了鏈?zhǔn)秸{(diào)用。我們用then來(lái)將多個(gè)Promise連接起來(lái),前一個(gè)promise resolve的結(jié)果是下一個(gè)promise中then的參數(shù)。

鏈?zhǔn)秸{(diào)用有什么缺點(diǎn)呢?

比如我們從一個(gè)promise中,resolve了一個(gè)值,我們需要根據(jù)這個(gè)值來(lái)進(jìn)行一些業(yè)務(wù)邏輯的處理。

假如這個(gè)業(yè)務(wù)邏輯很長(zhǎng),我們就需要在下一個(gè)then中寫(xiě)很長(zhǎng)的業(yè)務(wù)邏輯代碼。這樣讓我們的代碼看起來(lái)非常的冗余。

那么有沒(méi)有什么辦法可以直接返回promise中resolve的結(jié)果呢?

答案就是await。

當(dāng)promise前面加上await的時(shí)候,調(diào)用的代碼就會(huì)停止直到 promise 被解決或被拒絕。

注意await一定要放在async函數(shù)中,我們來(lái)看一個(gè)async和await的例子:

?
1
2
3
4
5
const logAsync = () => {
 return new Promise(resolve => {
 setTimeout(() => resolve('小馬哥'), 5000)
 })
}

上面我們定義了一個(gè)logAsync函數(shù),該函數(shù)返回一個(gè)Promise,因?yàn)樵揚(yáng)romise內(nèi)部使用了setTimeout來(lái)resolve,所以我們可以將其看成是異步的。

要是使用await得到resolve的值,我們需要將其放在一個(gè)async的函數(shù)中:

?
1
2
3
4
const doSomething = async () => {
 const resolveValue = await logAsync();
 console.log(resolveValue);
}

async的執(zhí)行順序

await實(shí)際上是去等待promise的resolve結(jié)果我們把上面的例子結(jié)合起來(lái):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const logAsync = () => {
 return new Promise(resolve => {
  setTimeout(() => resolve('小馬哥'), 1000)
 })
}
 
const doSomething = async () => {
 const resolveValue = await logAsync();
 console.log(resolveValue);
}
 
console.log('before')
doSomething();
console.log('after')

上面的例子輸出:

before
after
小馬哥

可以看到,aysnc是異步執(zhí)行的,并且它的順序是在當(dāng)前這個(gè)周期之后。

async的特點(diǎn)

async會(huì)讓所有后面接的函數(shù)都變成Promise,即使后面的函數(shù)沒(méi)有顯示的返回Promise。

?
1
2
3
4
5
const asyncReturn = async () => {
 return 'async return'
}
 
asyncReturn().then(console.log)

因?yàn)橹挥蠵romise才能在后面接then,我們可以看出async將一個(gè)普通的函數(shù)封裝成了一個(gè)Promise:

?
1
2
3
4
5
const asyncReturn = async () => {
 return Promise.resolve('async return')
}
 
asyncReturn().then(console.log)

總結(jié)

promise避免了回調(diào)地獄,它將callback inside callback改寫(xiě)成了then的鏈?zhǔn)秸{(diào)用形式。

但是鏈?zhǔn)秸{(diào)用并不方便閱讀和調(diào)試。于是出現(xiàn)了async和await。

async和await將鏈?zhǔn)秸{(diào)用改成了類(lèi)似程序順序執(zhí)行的語(yǔ)法,從而更加方便理解和調(diào)試。

我們來(lái)看一個(gè)對(duì)比,先看下使用Promise的情況:

?
1
2
3
4
5
6
7
8
9
const getUserInfo = () => {
 return fetch('/users.json') // 獲取用戶列表
 .then(response => response.json()) // 解析 JSON
 .then(users => users[0]) // 選擇第一個(gè)用戶
 .then(user => fetch(`/users/${user.name}`)) // 獲取用戶數(shù)據(jù)
 .then(userResponse => userResponse.json()) // 解析 JSON
}
 
getUserInfo()

將其改寫(xiě)成async和await:

?
1
2
3
4
5
6
7
8
9
10
const getUserInfo = async () => {
 const response = await fetch('/users.json') // 獲取用戶列表
 const users = await response.json() // 解析 JSON
 const user = users[0] // 選擇第一個(gè)用戶
 const userResponse = await fetch(`/users/${user.name}`) // 獲取用戶數(shù)據(jù)
 const userData = await userResponse.json() // 解析 JSON
 return userData
}
 
getUserInfo()

可以看到業(yè)務(wù)邏輯變得更加清晰。同時(shí),我們獲取到了很多中間值,這樣也方便我們進(jìn)行調(diào)試。

到此這篇關(guān)于nodejs中的異步編程知識(shí)點(diǎn)詳解的文章就介紹到這了,更多相關(guān)深入理解nodejs中的異步編程內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://www.cnblogs.com/flydean/p/14285436.html

延伸 · 閱讀

精彩推薦
  • node.jsNode.js ObjectWrap 的弱引用問(wèn)題

    Node.js ObjectWrap 的弱引用問(wèn)題

    最近在寫(xiě) Node.js Addon 的過(guò)程中,遇到了一個(gè)問(wèn)題,然后發(fā)現(xiàn)是 ObjectWrap 弱引用導(dǎo)致的,本文介紹一下具體的問(wèn)題和排查過(guò)程,以及 ObjectWrap 的使用問(wèn)題。...

    編程雜技9852022-01-04
  • node.js詳解node.js創(chuàng)建一個(gè)web服務(wù)器(Server)的詳細(xì)步驟

    詳解node.js創(chuàng)建一個(gè)web服務(wù)器(Server)的詳細(xì)步驟

    這篇文章主要介紹了詳解node.js創(chuàng)建一個(gè)web服務(wù)器(Server)的詳細(xì)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,...

    王佳斌8952021-12-31
  • node.jslinux服務(wù)器快速卸載安裝node環(huán)境(簡(jiǎn)單上手)

    linux服務(wù)器快速卸載安裝node環(huán)境(簡(jiǎn)單上手)

    這篇文章主要介紹了linux服務(wù)器快速卸載安裝node環(huán)境(簡(jiǎn)單上手),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需...

    mose-x8462022-01-22
  • node.jsk8s node節(jié)點(diǎn)重新加入master集群的實(shí)現(xiàn)

    k8s node節(jié)點(diǎn)重新加入master集群的實(shí)現(xiàn)

    這篇文章主要介紹了k8s node節(jié)點(diǎn)重新加入master集群的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋...

    Scarborought13922022-01-22
  • node.js在瀏覽器中,把 Vite 跑起來(lái)了!

    在瀏覽器中,把 Vite 跑起來(lái)了!

    大家好,我是 ssh,前幾天在推上沖浪的時(shí)候,看到 Francois Valdy 宣布他制作了 browser-vite[1],成功把 Vite 成功在瀏覽器中運(yùn)行起來(lái)了。這引起了我的興趣,如...

    前端從進(jìn)階到入院9282022-01-11
  • node.jsnodejs中使用worker_threads來(lái)創(chuàng)建新的線程的方法

    nodejs中使用worker_threads來(lái)創(chuàng)建新的線程的方法

    這篇文章主要介紹了nodejs中使用worker_threads來(lái)創(chuàng)建新的線程的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友...

    flydean程序那些事8982022-01-06
  • node.jsNode.js 中如何收集和解析命令行參數(shù)

    Node.js 中如何收集和解析命令行參數(shù)

    這篇文章主要介紹了Node.js 中如何收集和解析命令行參數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋...

    descire8802021-12-28
  • node.jsrequire加載器實(shí)現(xiàn)原理的深入理解

    require加載器實(shí)現(xiàn)原理的深入理解

    這篇文章主要給大家介紹了關(guān)于require加載器實(shí)現(xiàn)原理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需...

    隱冬8462022-03-03
主站蜘蛛池模板: 国产二区三区视频 | 狠狠操电影 | 国产精品久久国产精品 | 欧美成人精品欧美一级 | 一级国产航空美女毛片内谢 | 91系列在线观看 | 国产 视频 一区二区 | 成人激情综合网 | 精品三级内地国产在线观看 | 免费观看的毛片手机视频 | 性爱免费视频 | 免费观看国产精品视频 | 亚洲国产精品久久久久婷婷老年 | 91高清网站| 欧美videofree性欧美另类 | 日韩视频一二区 | 国产91大片 | 91色一区二区三区 | 西川av在线一区二区三区 | 国产1区2| 91成人在线免费视频 | 性爱在线免费视频 | 黄色7777 | 成人免费影院 | 全黄性性激高免费视频 | 免费毛片电影 | 姑娘第四集免费看视频 | 亚洲国产精品久久久久制服红楼梦 | 久久九九热re6这里有精品 | 成人免费网站在线观看视频 | 久久久综合视频 | 成人免费乱码大片a毛片视频网站 | 久久国产一级 | 一级黄色影院 | 九九精品在线播放 | 成人小视频免费在线观看 | 久久草草亚洲蜜桃臀 | 精品久久一区二区三区 | 国产午夜电影在线观看 | 免费视频aaa | av久草|