es6 --- promise和async/await的區別

首先需要了解async函數:

async是Generator函數的語法糖:

// 使用Generator依次讀取兩個文件
var fs = require('fs');
var readFile = function (fileName) {return new Promise(function (resolve, reject) {fs.readFile(filename, function(error, data) {if (error) return reject(error)resolve(data);});});
};// Generator
var gen = function* () {var f1 = yield readFile('/etc/fatab');var f2 = yield readFile('/etc/shells');console.log(f1.toString());console.log(f2.toString());
};// async
var ayncReadFile = async function () {var f1 = await readFile('/etc/fatab');var f2 = await readFile('/etc/shells');console.log(f1.toString());console.log(f2.toString());
};// async對Generator函數做了以下4點改變:
// 1. 內置執行器:async函數自帶執行器,使用方法為 asyncReadFile()
// 2. 更好的語義: async表示函數里有異步操作,await表示緊跟再后面的表達式需要等待結果
// 3. 更廣的適用性:yield命令后,只能是Thunk函數或Promise對象,而async函數的await命令后面,可以是Promise對象和原始類型的值
// 4.返回值是Promise對象,可以使用then方法指定下一步操作.// 注:async函數完全可以看作由多個異步操作包裝成的一個Promise,而await命令就是內部then命令的語法糖.

async函數的用法:

// 輸入name返回股票的價格
async function getStockPriceByName(name) {var symbol = await getStockSymbol(name);var stockPrice = await getStockPrice(symbol);return stockPrice;
}
getStockPriceByName('goog').then(function (result) {console.log(result);
});
// 非常同步的寫法!
// 從宏觀上來講,執行getStockPriceByName后,輸入名字,會得到一個stockPrice,而stockPrice是一個Promise數據結構,
// 其可以使用.then方法調用.// async封裝接口.
function timeout(ms) {return new Promise((resolve) => {setTimeout(resolve, ms);});
}
async function asyncPrint(value, ms) {await timeout(ms);console.log(value);
}asyncPrint("Hello", 50);

async的語法:

// async函數返回一個Promise對象
async function f() {return 'hello world';
}
fn().then(v => console.log(v))// async函數內部拋出的錯誤會導致返回的Promise對象變為reject狀態,
async function f(){throw new Error('出錯了');
}
f().then(v => console.log(v),e => console.log(e)
)

async的錯誤處理:

// 如果await后面的異步操作出錯,那么等同于async函數返回的Promise對象被reject.
async function f() {await new Promise(function (resolve, reject) {throw new Error('出錯了');});
}
f()
.then( v => console.log(v))
.catch( e => console.log(e))// async置于try...catch代碼塊中
async function f() {try{await new Promise(function (resolve, reject) {throw new Error('出錯了');});} catch (e) {}return await('hello world');
}// 多個await命令,同一放入try...catch結構中
async function main() {try {var val1 = await firstStep();var val2 = await secondStep(val1);var val3 = await thirdStep(val1, val2);console.log('Final: ', val3);}catch (err) {console.error(err);}
}// 使用try...catch結構,多次嘗試連接獲取某個url下的數據
const superagent = require('superagent');
const NUM_RETRIES = 3;async function test() {let i;for (i =0; i < NUM_RETRIES; ++i) {try {await superagent.get('http://google.com/this-throws-an-error');break;} catch(err) {}}cosnole.log(i);    // 3
}
test();

async使用注意點:

// 1.await命令后面的Promise對象的運行結果可能是rejected,所以最好把await命令放在try...catch代碼塊中
// 寫法一
async function myFunction() {try{await somethingThatReturnsAPromise();} catch (err) {console.log(err);}
}
// 寫法二
async function myFunction() {try{await somethingThatReturnsAPromise().catch(function(err){console.log(err);});}
}// 2.多個await命令后面的異步操作如果不存在繼發關系,最好讓它們同時觸發
// 寫法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);// 寫法二
// let fooPromise = getFoo();
// let barPromise = getBar();
// let foo = await fooPromise;
// let bar = await barPromise;// 3.await命令只能用在async函數之中,如果用在普通函數中就會報錯
async function dbFunc(db) {let docs = [ {}, {}, {] ];// 報錯docs.forEach(function (doc) {await db.post(doc);});
}
// 報錯的原因在于,async用在普通函數function(doc)之中.
// 考慮forEach的參數改為async 函數,
function dbFunc(db) {let docs = [ {}, {}, {} ];docs.forEach(async function(doc) {await db.post(doc);});
}
// 注:forEach是并發執行的,因此以上還是會報錯.// 如果想繼發的將doc推入db.post,可以采用for...of...
function dbFunc(db) {let docs = [ {}, {}, {} ];for (let doc of docs) {await db.post(doc);}
}// 使用Promise.all 執行并發
function dbFunc(db) {let docs = [ {}, {}, {} ];let promises = docs.map( (doc) => db.post(doc));let results = Promise.all(promises);console.log(results);
}// 使用for...of的 并發執行
function dbFunc(db) {let docs = [ {}, {}, {} ];let promises = docs.map( (doc) => db.post(doc));let results = [];for (let promise of promises) {results.push(promise);}console.log(results);
}

promise與async/await的區別:

// 1.錯誤處理:Async/await使得處理同步 + 異步成為了現實
//           在try/catch中,難以處理JSON.parse拋出的錯誤,原因在于,這個錯誤發生在Promise內部.
//           要處理以上錯誤,只能在Promise外面套上一層try...catch
//           async/await,后面的異步操作若出錯,那么等同于async函數返回的Promise對象被reject// Promise   try...catch
const makeRequest = () => {try {getJSON().then(result => {const data = JSON.parse(result);console.log(data);})} catch (err) {console.log(err)}
}
// 使用async/await
const makeRequest = () => {try {const data =JSON.parse(await getJSON())console.log(data)} catch (err) {console.log(err)}
}	// 2.條件判別 (Conditionals):根據得到的數據決定下一步操作
const makeRequest = () => {return getJSON().then(data => {if ( data.needsAnotherRequest) {return makeAnoterReuqest(data).then(moreData => {console.log(moreData)return  moreData})} else {console.log(data);return data;}})
}
// 以上就2次就嵌套得如此深,要是10次...100次......
// 使用async可以很好的寫出可維護性代碼
const makeRequest = () => {const data = await getJSON();if( data.needsAnotherRequest) {const moreData = await makeAnotherRequest(data);console.log(moreData)return moreData} else {console.log(data);return data;}
}
// 可讀性和可維護性更強!// 3.對中間的值的使用更簡單]
// promise
const makeRequest = () => {return promise1().then (value1 => {return promise2(value1).then( value2 => {return promise3 (value1, value2)})})
}// async
const makeRequest  = () => {const value1 = await promise1()const value2 = await promise2(value1)const value3 = await promise3(value1, value2)return value3
}
// 我天,,,同步的寫法,,!! 簡單明了,好維護!  

參考《ES6標準入門》(第3版) P375~P385
參考 ES6 Async/Await與Promise區別

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/251080.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/251080.shtml
英文地址,請注明出處:http://en.pswp.cn/news/251080.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ueditor百度編輯器中的 setContent()方法的使用

百度編輯器Ueditor所提供的setContent()方法作用是&#xff1a;設置或者改變編輯器里面的文字內容或html內容 函數說明&#xff1a;setContent(string,boolean); 參數string 是需要設置到編輯器里面的內容&#xff0c;可以含有HTML代碼&#xff0c;最后插入到編輯器中的內容是經…

小程序UI

從input組件說起 <input maxlength"10" placeholder"最大輸入長度10" /> <div id"wrapper" disabled$"{{disabled}}">\n <p id"placeholder" class$"{{_getPlaceholderClass(placeholderClass)}}"…

61-1 認識webpack

認識webpack 面向過程開發的不便引入外部js執行順序面向對象開發 加載多個文件耗時更多 增加了http請求 引入過多js變量來源不明 優化 使用前先import 但使用import語法需要借助工具webpack翻譯為瀏覽器可以解析的語法安裝node自動攜帶npmwebpack若沒有全局安裝 需要使用npx…

css font簡寫

一、字體屬性主要包括下面幾個 font-family&#xff0c;font-style&#xff0c;font-variant&#xff0c;font-weight&#xff0c;font-size&#xff0c;fontfont-family&#xff08;字體族&#xff09;: “Arial”、“Times New Roman”、“宋體”、“黑體”等;font-style&…

javascript --- 原生的拖拽功能實現

準備一個方塊: <style>.drag{background-color:#aaf;position:absolute;} </style> <div class"drag" style"width:100px;height:100px;top:0;left:0"></div>監聽鼠標的按住事件: let dragDiv document.getElementsByClassName…

web安全學習-驗證機制存在的問題

驗證機制是應用程序防御惡意攻擊的中心機制。它處于防御未授權的最前沿&#xff0c;如果用戶能夠突破那些防御&#xff0c;他們通常能夠控制應用程序的全部功能&#xff0c;自由訪問其中的數據。缺乏安全穩定的驗證機制&#xff0c;其他核心安全機制&#xff08;如回話管理和訪…

ES5-拓展 原型鏈、繼承、類

Symbol不是構造函數 Object不是原型是實例對象 他的構造器繼承原型上的構造器 undefined是未定義 null是空指針 一、原型鏈 1. 函數也是實例對象 2. 構造函數Object是由Function構造出來的 3. 有一種說法是&#xff0c;原型鏈的終點是null Object.prototype.__proto__指向nul…

Mysql中各種與字符編碼集(character_set)有關的變量含義

mysql涉及到各種字符集&#xff0c;在此做一個總結。 字符集的設置是通過環境變量來設置的&#xff0c;環境變量和linux中的環境變量是一個意思。mysql的環境變量分為兩種&#xff1a;session和global。session變量是僅在這次會話紅中有效&#xff0c;在mysql中&#xff0c;一次…

spring boot 加載application配置文件

這就要注意了 轉載于:https://www.cnblogs.com/huochaihe/p/9397849.html

javascript --- 防抖與節流

先做一個監聽鼠標移動的base: <style>#content{height:150px;width:200px;text-align:center;color:#fff;background-color:#ccc;font-size: 70px;} </style> <div id"content"></div> <script>let content document.getElementById…

DOM-9 【實戰】模塊化開發Todolist(面向過程)

模塊化分類 按dom結構劃分按功能劃分&#xff08;組件化開發&#xff09; 模塊與模塊之間可以相互依賴&#xff0c;但互不影響 模塊&#xff1a;IIFE賦值給一個變量&#xff0c;當引入模塊時&#xff0c;IIFE會立即執行 單標簽閉合才符合W3C規范display、position放在上面css是…

mysql在linux下的安裝(5.7版本以后)

1.添加mysql組和mysql用戶&#xff0c;用于設置mysql安裝目錄文件所有者和所屬組。 ①groupadd mysql ②useradd -r -g mysql mysql 2.將二進制文件解壓到指定的安裝目錄&#xff0c;通用的/usr/local ①解壓二進制文件&#xff0c; tar -zxvf /usr/local/mysql-5.7.13-linux-…

Kali Linux2018 上安裝open-vm-tools實現虛擬機交互

最新的kali linux2018已經不再支持原有的vmwaretools&#xff0c;即使安裝了也不能實現主機與客戶機之間的交互&#xff08;比如從主機復制文件到客戶機&#xff09;。安裝open-vm-tools替代vm tools能夠完美實現“自動適應客戶機”&#xff08;即自動適應客戶機的分辨率&#…

DOM-11 【兼容】鼠標行為坐標系、pageXY封裝、拖拽函數封裝

鼠標行為 e.屬性含義相關屬性clientX/Y鼠標位置相對于當前可視區域的坐標x/y&#xff08;FF火狐部分版本不支持&#xff09;pageX/Y(IE9以下不支持)鼠標位置相對于當前文檔的坐標layerX/Y (IE11以下同clientX/Y)screenX/Y鼠標位置相對于顯示器屏幕的坐標offsetX/Y鼠標位置相對…

java --replaceAll方法

public void abc(){String str "aabbccdd";str str.replaceAll("\\d","數字")&#xff1b;system.out.println("str"); } 轉載于:https://www.cnblogs.com/gjack/p/8325778.html

mysql分頁優化

一般分頁這樣寫 select * from goods limit 50,20 從50行開始取20行&#xff0c;即第51行到70行 當數據量少當時候這樣并沒有什么問題&#xff0c;但是如果 select * from goods limit 1000000,20 查詢耗時驟升。 這種方式是查詢出100000020行&#xff0c;再取20行&#xff0c;…

DOM-10 面向對象開發Todolist

將插件配置項寫在html的div里&#xff0c;data-config自定義屬性&#xff0c;外單引號&#xff0c;內雙引號&#xff08;內部是JSON字符串&#xff09; <div class"todo-wrap" data-config{"plusBtn":"j-show-input","inputArea":…

計網 --- 域名服務系統:因特網的目錄服務

主機名: // 主機的一種標識方法如: cnn.com www.yahoo.com gaia.cs.umass.edu cis.poly.edu主機名可能由不定長的字母數字組成,路由器難以處理.由于這些原因, 主機也可以使用IP地址(IP address) 進行標識 // 簡略介紹ip地址 // 一個IP地址由4個字節組成,并有著嚴格的層次結構…

Ansible基礎概述

一、Ansible簡介 Ansible基于Python語言實現&#xff0c;由paramiko和PyYAML兩個關鍵模塊構建。Ansible的編排引擎可以出色地完成配置管理&#xff0c;流程控制&#xff0c;資源部署等多方面工作。Ansible公司負責Ansible開源軟件的維護&#xff0c;管理。一般軟件的更新大概每…

selenium瀏覽器驅動下載地址整理

今天把手頭有的一些關于selenium測試的資源整理了一下&#xff0c;分享出來。 1. 所有版本chrome下載 是不是很難找到老版本的chrome&#xff1f;博主收集了幾個下載chrome老版本的網站&#xff0c;其中哪個下載的是原版的就不得而知了。 http://www.slimjet.com/chrome/google…