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

JavaScript詳解使用Promise處理回調(diào)地獄與async?await修飾符

 更新時間:2022年07月19日 11:54:20   作者:一個水瓶座程序猿.  
這篇文章主要介紹了JavaScript使用Promise處理回調(diào)地獄與async?await修飾符,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

Promise

Promise能夠處理異步程序。

回調(diào)地獄

JS中或node中,都大量的使用了回調(diào)函數(shù)進(jìn)行異步操作,而異步操作什么時候返回結(jié)果是不可控的,如果我們希望幾個異步請求按照順序來執(zhí)行,那么就需要將這些異步操作嵌套起來,嵌套的層數(shù)特別多,就會形成回調(diào)地獄 或者叫做 橫向金字塔。

案例:有a.txt、b.txt、c.txt三個文件,使用fs模板按照順序來讀取里面的內(nèi)容,代碼:

// 將讀取的a、b、c里面的內(nèi)容,按照順序輸出
const fs = require('fs');
// 讀取a文件
fs.readFile('./a.txt','utf-8',(err,data)=>{
    if(err) throw err;
    console.log(data);
    // 讀取b文件
    fs.readFile('./b.txt','utf-8',(err,data)=>{
       	if(err) throw err;
        console.log(data);
        // 讀取c文件
        fs.readFile('./c.txt','utf-8',(err,data)=>{
            if(err) throw err;
            console.log(data)
        })
    })
})

案例中,循環(huán)嵌套的代碼越來越多,這就是 地獄回調(diào)

Promise簡介

  • Promise對象可以解決 回調(diào)地獄 的問題
  • Promise是異步編程的一種解決方案,比傳統(tǒng)的解決方案(回調(diào)函數(shù)和事件)更合理更強(qiáng)大
  • Promise可以理解為是一個容器,里面可以編寫異步程序的代碼
  • 從語法上說,Promise是一個對象,使用的時候需要 new

Promise簡單使用

Promise是“承諾”的意思,實例中,它里面的異步操作就相當(dāng)于一個承諾,而承諾就會有兩種結(jié)果,要么完成了承諾的內(nèi)容,要么失敗。

所以,使用Promise,分為兩大部分,首先是有一個承諾(異步操作),然后再兌現(xiàn)結(jié)果。

第一部分:定義"承諾"

// 實例化一個Promise,表示定義一個容器,需要給它傳遞一個函數(shù)作為參數(shù),而該函數(shù)又有兩個形參,通常用resolve和reject表示。該函數(shù)里面可以寫異步請求的代碼
// 換個角度,也可以理解為定下了一個承諾諾
let p = new Promise((resolve,reject)=>{
    // 形參resolve,單詞意思是 完成
    // 實參reject,單詞意思是 失敗
    fs.readFile('./a.txt','utf-8',(err,data)=>{
        if(err){
            // 失敗,就告訴別人,承諾失敗了
            reject(err);
        }else{
            // 成功,就告訴別人,承諾實現(xiàn)了
            resolve(data);
        }
    }
})

第二部分:獲取"承諾"的結(jié)果

// 通過調(diào)用 p 的then方法,可以獲取到上述 "承諾" 的結(jié)果
// then方法有兩個函數(shù)類型的參數(shù),參數(shù)1表示承諾成功時調(diào)用的函數(shù),參數(shù)2可選,表示承諾失敗時調(diào)用的函數(shù)
// p.then(
//	(data)=>{},  // 函數(shù)類型的參數(shù),用于獲取承諾成功后的數(shù)據(jù)
//   (err)=>{}   // 函數(shù)類型的參數(shù),用于承諾失敗后的錯誤信息
//)
p.then(
	(data)=>{
        console.log(data);
    },
    (err)=>{
        console.log(err);
    }
)

三種狀態(tài)

  • 最初狀態(tài):pending,等待中,此時的promise結(jié)果為undefined
  • 當(dāng)resolve (value) 調(diào)用時,達(dá)到最終狀態(tài)之一:fulfilled,(成功的)完成,此時可以獲取結(jié)果value
  • 當(dāng)reject (error) 調(diào)用時,達(dá)到最終狀態(tài)之一:rejected,失敗,此時可以獲取錯誤信息error

當(dāng)達(dá)到最終的fulfilled 或 rejected 時,promise的狀態(tài)就不會再改變了。

特點

當(dāng)調(diào)用 resolve的時候,Promise 將到達(dá)最終的狀態(tài)。 達(dá)到最終狀態(tài)之后,Promise的狀態(tài)就不會再改變了。

多次調(diào)用resolve函數(shù),只有第一次有效,其他的調(diào)用都無效。

const fs = require('fs');
// 1.創(chuàng)建Promise對象:(承諾)
let p = new Promise((resolve,reject)=>{
    resolve(123);
    resolve(456);  // 這次的調(diào)用無效
});
// 2.獲取異步任務(wù)的結(jié)果
// p.then(函數(shù)1,[函數(shù)2]);
p.then(res =>{
    console.log(res);  // 123
},err =>{
    console.log(err);
})

then方法的鏈?zhǔn)秸{(diào)用

  • 前一個then里面返回的字符串,會被下一個then方法接收到。但是沒有意義;
  • 前一個then里面返回的Promise對象,并且調(diào)用resolve的時候傳遞了數(shù)據(jù),數(shù)據(jù)會被下一個then接收到
  • 前一個then里面如果沒有調(diào)用resolve,則后續(xù)的then不會接收到任何值
const fs = require('fs');
// promise 承諾
let p1 = new Promise((resolve, reject) => {
  fs.readFile('./a.txt', 'utf-8', (err, data) => {
    err ? reject(err) : resolve(data.length);
  });
});
let p2 = new Promise((resolve, reject) => {
  fs.readFile('./b.txt', 'utf-8', (err, data) => {
    err ? reject(err) : resolve(data.length);
  });
});
let p3 = new Promise((resolve, reject) => {
  fs.readFile('./c.txt', 'utf-8', (err, data) => {
    err ? reject(err) : resolve(data.length);
  });
});
p1.then(a => {
  console.log(a);
  return p2;
}).then(b => {
  console.log(b);  	// 接收上面?zhèn)鬟f的值p2
  return p3;
}).then(c => {
  console.log(c)   	// 接收上面?zhèn)鬟f的值p3
}).catch((err) => {
  console.log(err);   // 如果錯誤,打印報錯信息
});

catch方法可以統(tǒng)一獲取到 錯誤信息

封裝按順序異步讀取文件的函數(shù)

function myReadFile(path) {
    return new Promise((resolve, reject) => {
        fs.readFile(path, 'utf-8', (err, data) => {
            err ? reject(err) : resolve(data.length);
        })
    });
}
myReadFile('./a.txt')
.then(a => {
  console.log(a);
  return myReadFile('./b.txt');
})
.then(b => {
  console.log(b);
  return myReadFile('./c.txt');
})
.then(c => {
  console.log(c)
})
.catch((err) => {
  console.log(err);
});

使用第三方模塊讀取文件

  • npm init - y
  • npm i then-fs 安裝then-fs模塊
  • then-fs 將 內(nèi)置的fs模塊封裝了,讀取文件后,返回 Promise 對象,省去了我們自己封裝
// then-fs 模塊是第三方模塊,需要 npm install then-fs  下載安裝的
const fs = require('then-fs');
// then-fs 對內(nèi)置的fs模塊進(jìn)行了重寫的封裝。調(diào)用方法后,返回Promise對象
let p1 = fs.readFile('./files/a.txt', 'utf-8');  // 
let p2 = fs.readFile('./files/b.txt', 'utf-8');
let p3 = fs.readFile('./files/c.txt', 'utf-8');
// 通過then獲取結(jié)果
p1.then(res => {
  console.log(res.length);
  return p2;
}).then(res => {
  console.log(res.length);
  return p3;
}).then(res => {
  console.log(res.length);
})

async和await 修飾符

ES6 — ES2015

async 和 await 是 ES2017 中提出來的。

異步操作是 JavaScript 編程的麻煩事,麻煩到一直有人提出各種各樣的方案,試圖解決這個問題。

從最早的回調(diào)函數(shù),到 Promise 對象,再到 Generator 函數(shù),每次都有所改進(jìn),但又讓人覺得不徹底。它們都有額外的復(fù)雜性,都需要理解抽象的底層運行機(jī)制。

異步I/O不就是讀取一個文件嗎,干嘛要搞得這么復(fù)雜?異步編程的最高境界,就是根本不用關(guān)心它是不是異步。

async 函數(shù)就是隧道盡頭的亮光,很多人認(rèn)為它是異步操作的終極解決方案。

ES2017 提供了async和await關(guān)鍵字。await和async關(guān)鍵詞能夠?qū)惒秸埱蟮慕Y(jié)果以返回值的方式返回給我們。

async 用于修飾一個 function

  • async 修飾的函數(shù),總是返回一個 Promise 對象
  • 函數(shù)內(nèi)的返回值,將自動包裝在 resolved 的 promise 中

await 只能出現(xiàn)在 async 函數(shù)內(nèi)

  • await 讓 JS 引擎等待直到promise完成并返回結(jié)果
  • 語法:let value = await promise對象; // 要先等待promise對象執(zhí)行完畢,才能得到結(jié)果
  • 由于await需要等待promise執(zhí)行完畢,所以await會暫停函數(shù)的執(zhí)行,但不會影響其他同步任務(wù)

對于錯誤處理,可以選擇在async函數(shù)后面使用 .catch() 或 在promise對象后使用 .catch()

const fs = require('fs');
// 將異步讀取文件的代碼封裝
function myReadFile (path) {
    return new Promise((resolve, reject) => {
        fs.readFile(path, 'utf-8', (err, data) => {
            err ? reject(err) : resolve(data.length);
        });
    }).catch(err => {
        console.log(err);
    });
}
async function abc () {
    let a = await myReadFile('./a.txt');
    let b = await myReadFile('./b.txt');
    let c = await myReadFile('./c.txt');
    console.log(b);
    console.log(a);
    console.log(c);
}
abc();

錯誤處理

前提是得到幾個Promise對象,代碼如下:

let fs = require('fs');
let p1 = new Promise('./files/a.txt','utf-8');
let p2 = new Promise('./files/bbb.txt','utf-8');  // 注意:這里故意寫錯路徑
let p3 = new Promise('./files/c.txt','utf-8');

獲取Promise的結(jié)果,可以通過then獲取。也可以通過async和await獲取。

如果使用then獲取結(jié)果,那么錯誤如何處理?在鏈?zhǔn)秸{(diào)用的尾端,加一個catch方法即可

// ----------------------------通過 then 獲取結(jié)果-----------------------------
p1.then(res=>{
    console.log(res);
    return p2;
}).then(res=>{
    console.log(res);
    return p3
}).catch(err=>{
    console.log(err);
})

如何使用async和await獲取結(jié)果,最好的錯誤處理方案,就是使用 try...catch...

// ---------------------------通過 async/await 獲取結(jié)果--------------------
async function abc(){
    try{  // 嘗試做一些事情
        let r1 = await p1;  // 正常獲取結(jié)果
        let r2 = await p2;  // 這里出錯了,就會拋出錯誤 throw err.
        let r3 = await p3;
        console.log(r1,r2,r3)
    }catch(e){
        console.log(e);  // catch這里,會抓住前面try里面拋出的錯誤
    }
}
abc();

小結(jié)

Promise是異步任務(wù)的一種解決方案

得到Promise對象

  • 自己new Promise()
  • 自己封裝函數(shù),函數(shù)中返回 Promise對象
  • 使用第三方的模塊或者庫。比如 then-fs ,比如 axios

獲取結(jié)果

  • 通過 then 方法獲取,并且通過 catch 捕獲錯誤信息
  • 通過 async和await的配合獲取結(jié)果,并且通過 try…catch…捕獲錯誤

到此這篇關(guān)于JavaScript詳解使用Promise處理回調(diào)地獄與async await修飾符的文章就介紹到這了,更多相關(guān)JavaScript Promise回調(diào)地獄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JavaScript實例--實現(xiàn)計算器

    JavaScript實例--實現(xiàn)計算器

    這篇文章主要介紹了JavaScript實現(xiàn)計算器,下面文章實現(xiàn)計算器作為學(xué)習(xí)期間的一個小練習(xí),需要的小伙伴可以參考一下,希望對你有所幫助
    2022-01-01
  • D3.js進(jìn)階系列之CSV表格文件的讀取詳解

    D3.js進(jìn)階系列之CSV表格文件的讀取詳解

    D3.js支持從外部讀取數(shù)據(jù)進(jìn)行圖形交互(Loading External Resources),支持的格式有CSV、txt、Html、tsv、xml文本文件和JSON XML數(shù)據(jù)結(jié)構(gòu),下面這篇文章主要給大家介紹了D3.js中CSV表格文件讀取的相關(guān)資料,需要的朋友可以參考下。
    2017-06-06
  • js點擊任意區(qū)域彈出層消失實現(xiàn)代碼

    js點擊任意區(qū)域彈出層消失實現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了js點擊任意區(qū)域彈出層消失實現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • js實現(xiàn)簡單的秒表

    js實現(xiàn)簡單的秒表

    這篇文章主要為大家詳細(xì)介紹了js實現(xiàn)簡單的秒表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-01-01
  • JavaScript中Promise的執(zhí)行順序詳解

    JavaScript中Promise的執(zhí)行順序詳解

    Promise 是 JS 中進(jìn)行異步編程的新的解決方案(舊的是純回調(diào)形式) ,下面這篇文章主要給大家介紹了關(guān)于JavaScript中Promise執(zhí)行順序的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-01-01
  • JS實現(xiàn)淘寶支付寶網(wǎng)站的控制臺菜單效果

    JS實現(xiàn)淘寶支付寶網(wǎng)站的控制臺菜單效果

    這篇文章主要介紹了JS實現(xiàn)淘寶支付寶網(wǎng)站的控制臺菜單效果,涉及JavaScript基于時間函數(shù)及數(shù)學(xué)運算控制頁面動畫彈出菜單效果的實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09
  • 一個加載js文件的小腳本

    一個加載js文件的小腳本

    一個加載js文件的小腳本...
    2007-06-06
  • js 調(diào)用百度地圖api并在地圖上進(jìn)行打點添加標(biāo)注

    js 調(diào)用百度地圖api并在地圖上進(jìn)行打點添加標(biāo)注

    上邊有一個標(biāo)題,下邊分成兩塊,左邊是地圖。并且地圖上有兩個點,點擊兩個點有相應(yīng)的提示信息,具體實現(xiàn)如下
    2014-05-05
  • js實現(xiàn)綠白相間豎向網(wǎng)頁百葉窗動畫切換效果

    js實現(xiàn)綠白相間豎向網(wǎng)頁百葉窗動畫切換效果

    這篇文章主要介紹了js實現(xiàn)綠白相間豎向網(wǎng)頁百葉窗動畫切換效果,實例分析了javascript實現(xiàn)百葉窗動畫效果的技巧,需要的朋友可以參考下
    2015-03-03
  • 基于JavaScript實現(xiàn)單例模式

    基于JavaScript實現(xiàn)單例模式

    這篇文章主要介紹了基于JavaScript實現(xiàn)單例模式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10

最新評論