摘要:使用時(shí)也要注意范圍和層級。服務(wù)端配置服務(wù)端使用,最簡單的方式是通過。云引擎是推出的服務(wù)器端運(yùn)行環(huán)境,支持和環(huán)境,功能強(qiáng)大而且目前免費(fèi),結(jié)合,使原本復(fù)雜的開發(fā)工作變得簡單高效。目前也支持和海外節(jié)點(diǎn),輕松滿足你的業(yè)務(wù)需求。
構(gòu)建一個(gè)應(yīng)用程序總是會面對異步調(diào)用,不論是在 Web 前端界面,還是 Node.js 服務(wù)端都是如此,JavaScript 里面處理異步調(diào)用一直是非常惡心的一件事情。以前只能通過回調(diào)函數(shù),后來漸漸又演化出來很多方案,最后 Promise 以簡單、易用、兼容性好取勝,但是仍然有非常多的問題。其實(shí) JavaScript 一直想在語言層面徹底解決這個(gè)問題,在 ES6 中就已經(jīng)支持原生的 Promise,還引入了 Generator 函數(shù),終于在 ES7 中決定支持 async 和 await。
基本語法async/await 究竟是怎么解決異步調(diào)用的寫法呢?簡單來說,就是將異步操作用同步的寫法來寫。先來看下最基本的語法(ES7 代碼片段):
const f = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(123); }, 2000); }); }; const testAsync = async () => { const t = await f(); console.log(t); }; testAsync();
首先定義了一個(gè)函數(shù) f,這個(gè)函數(shù)返回一個(gè) Promise,并且會延時(shí) 2 秒,resolve 并且傳入值 123。testAsync 函數(shù)在定義時(shí)使用了關(guān)鍵字 async,然后函數(shù)體中配合使用了 await,最后執(zhí)行 testAsync。整個(gè)程序會在 2 秒后輸出 123,也就是說 testAsync 中常量 t 取得了 f 中 resolve 的值,并且通過 await 阻塞了后面代碼的執(zhí)行,直到 f 這個(gè)異步函數(shù)執(zhí)行完。
對比 Promise僅僅是一個(gè)簡單的調(diào)用,就已經(jīng)能夠看出來 async/await 的強(qiáng)大,寫碼時(shí)可以非常優(yōu)雅地處理異步函數(shù),徹底告別回調(diào)惡夢和無數(shù)的 then 方法。我們再來看下與 Promise 的對比,同樣的代碼,如果完全使用 Promise 會有什么問題呢?
const f = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(123); }, 2000); }); }; const testAsync = () => { f().then((t) => { console.log(t); }); }; testAsync();
從代碼片段中不難看出 Promise 沒有解決好的事情,比如要有很多的 then 方法,整塊代碼會充滿 Promise 的方法,而不是業(yè)務(wù)邏輯本身,而且每一個(gè) then 方法內(nèi)部是一個(gè)獨(dú)立的作用域,要是想共享數(shù)據(jù),就要將部分?jǐn)?shù)據(jù)暴露在最外層,在 then 內(nèi)部賦值一次。雖然如此,Promise 對于異步操作的封裝還是非常不錯(cuò)的,所以 async/await 是基于 Promise 的,await 后面是要接收一個(gè) Promise 實(shí)例。
對比 RxJSRxJS 也是非常有意思的東西,用來處理異步操作,它更能處理基于流的數(shù)據(jù)操作。舉個(gè)例子,比如在 Angular2 中 http 請求返回的就是一個(gè) RxJS 構(gòu)造的 Observable Object,我們就可以這樣做:
$http.get(url) .map(function(value) { return value + 1; }) .filter(function(value) { return value !== null; }) .forEach(function(value) { console.log(value); }) .subscribe(function(value) { console.log("do something."); }, function(err) { console.log(err); });
如果是 ES6 代碼可以進(jìn)一步簡潔:
$http.get(url) .map(value => value + 1) .filter(value => value !== null) .forEach(value => console.log(value)) .subscribe((value) => { console.log("do something."); }, (err) => { console.log(err); });
可以看出 RxJS 對于這類數(shù)據(jù)可以做一種類似流式的處理,也是非常優(yōu)雅,而且 RxJS 強(qiáng)大之處在于你還可以對數(shù)據(jù)做取消、監(jiān)聽、節(jié)流等等的操作,這里不一一舉例了,感興趣的話可以去看下 RxJS 的 API。
這里要說明一下的就是 RxJS 和 async/await 一起用也是可以的,Observable Object 中有 toPromise 方法,可以返回一個(gè) Promise Object,同樣可以結(jié)合 await 使用。當(dāng)然你也可以只使用 async/await 配合 underscore 或者其他庫,也能實(shí)現(xiàn)很優(yōu)雅的效果。總之,RxJS 與 async/await 不沖突。
異常處理通過使用 async/await,我們就可以配合 try/catch 來捕獲異步操作過程中的問題,包括 Promise 中 reject 的數(shù)據(jù)。
const f = () => { return new Promise((resolve, reject) => { setTimeout(() => { reject(234); }, 2000); }); }; const testAsync = () => { try { const t = await f(); console.log(t); } catch (err) { console.log(err); } }; testAsync();
代碼片段中將 f 方法中的 resolve 改為 reject,在 testAsync 中,通過 catch 可以捕獲到 reject 的數(shù)據(jù),輸出 err 的值為 234。try/catch 使用時(shí)也要注意范圍和層級。如果 try 范圍內(nèi)包含多個(gè) await,那么 catch 會返回第一個(gè) reject 的值或錯(cuò)誤。
const f1 = () => { return new Promise((resolve, reject) => { setTimeout(() => { reject(111); }, 2000); }); }; const f2 = () => { return new Promise((resolve, reject) => { setTimeout(() => { reject(222); }, 3000); }); }; const testAsync = () => { try { const t1 = await f1(); console.log(t1); const t2 = await f2(); console.log(t2); } catch (err) { console.log(err); } }; testAsync();
如代碼片段所示,testAsync 函數(shù)體中 try 有兩個(gè) await 函數(shù),而且都分別 reject,那么 catch 中僅會觸發(fā) f1 的 reject,輸出的 err 值是 111。
開始使用無論是 Web 前端還是 Node.js 服務(wù)端,都可以通過預(yù)編譯的手段實(shí)現(xiàn)使用 ES6 和 ES7 來寫代碼,目前最流行的方案是通過 Babel 將使用 ES7、ES6 寫的代碼編譯為 E6 或 ES5 的代碼來執(zhí)行。
Node.js 服務(wù)端配置服務(wù)端使用 Babel,最簡單的方式是通過 require hook。
首先安裝 Babel:
$ npm install babel-core --save
安裝 async/await 支持:
$ npm install babel-preset-stage-3 --save
在服務(wù)端代碼的根目錄中配置 .babelrc 文件,內(nèi)容為:
{ "presets": ["stage-3"] }
在頂層代碼文件(server.js 或 app.js 等)中引入 Babel 模塊:
require("babel-core/register");
在這句后面引入的模塊,都將會自動通過 babel 編譯,但當(dāng)前文件不會被 babel 編譯。另外,需要注意 Node.js 的版本,如果是 4.0 以上的版本則默認(rèn)支持絕大部分 ES6,可以直接啟動。但是如果是 0.12 左右的版本,就需要通過 node —harmory 來啟動才能夠支持。因?yàn)?stage-3 模式,Babel 不會編譯基本的 ES6 代碼,環(huán)境既然支持又何必要編譯為 ES5?這樣做也是為了提高性能和編譯效率。
配置 Web 前端構(gòu)建可以通過增加 Gulp 的預(yù)編譯 task 來支持。
首先安裝 gulp-babel 插件:
$ npm install gulp-babel --save-dev
然后編寫配置:
var gulp = require("gulp"); var babel = require("gulp-babel"); gulp.task("babel", function() { return gulp.src("src/app.js") .pipe(babel()) .pipe(gulp.dest("dist")); });
除了 Gulp-babel 插件,也可以使用官方的 Babel-loader 結(jié)合 Webpack 或 Browserify 使用。
要注意的是,雖然官方也有純?yōu)g覽器版本的 Babel.js,但是瀏覽器限制非常多,而且對客戶端性能影響也較大,不推薦使用。
LeanEngine Full StackLeanEngine(云引擎)是 LeanCloud 推出的服務(wù)器端運(yùn)行環(huán)境,支持 Node.js 和 Python 環(huán)境,功能強(qiáng)大而且目前免費(fèi),結(jié)合 LeanCloud JavaScript SDK,使原本復(fù)雜的開發(fā)工作變得簡單高效。目前也支持 Redis 和海外節(jié)點(diǎn),輕松滿足你的業(yè)務(wù)需求。
LeanCloud 使用自已的服務(wù)編寫出了很多的應(yīng)用和 Web 產(chǎn)品。為了方便各位開發(fā)者基于 LeanEngine 來開發(fā)應(yīng)用,LeanCloud 整理了目前開發(fā) Web 端產(chǎn)品的技術(shù)棧,并結(jié)合 LeanEngine 特點(diǎn),推出了一套完整實(shí)用的技術(shù)解決方案:LeanEngine-Full-Stack,它已經(jīng)配置了 Babel,可以在 LeanEngine 中結(jié)合 JavaScript SDK 使用 async/await 處理異步操作。所以,還等什么?快來下載編寫新項(xiàng)目吧。
Enjoy!
結(jié)語LeanCloud 希望能夠通過構(gòu)建最簡單易用的技術(shù)產(chǎn)品,幫助各位開發(fā)者和創(chuàng)業(yè)者加速產(chǎn)品開發(fā),盡可能地節(jié)約資源成本、時(shí)間成本和機(jī)會成本,希望本文能夠幫助到你。有什么問題,可以在 LeanEngine-Full-Stack @GitHub 倉庫 中提交 issue,或者直接去 LeanCloud 社區(qū) 提問。
【參考資料】EcmaScript async/await 詳細(xì)規(guī)范
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/86252.html
摘要:的翻譯文檔由的維護(hù)很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:但是的的出現(xiàn)碉堡的新朋友,我們可以輕松寫出同步風(fēng)格的代碼同時(shí)又擁有異步機(jī)制,可以說是目前最簡單,最優(yōu)雅,最佳的解決方案了。不敢說這一定是終極的解決方案,但確實(shí)是目前最優(yōu)雅的解決方案 一、異步解決方案的進(jìn)化史 JavaScript的異步操作一直是個(gè)麻煩事,所以不斷有人提出它的各種解決方案。可以追溯到最早的回調(diào)函數(shù)(ajax老朋友),到Promise(不算新的朋友),再到ES6的Gener...
摘要:最受歡迎的引擎是,在和中使用,用于,以及所使用的。單線程的我們說是單線程的,因?yàn)橛幸粋€(gè)調(diào)用棧處理我們的函數(shù)。也就是說,如果有其他函數(shù)等待執(zhí)行,函數(shù)是不能離開調(diào)用棧的。每個(gè)異步函數(shù)在被送入調(diào)用棧之前必須通過回調(diào)隊(duì)列。 翻譯:瘋狂的技術(shù)宅原文:https://www.valentinog.com/bl... 本文首發(fā)微信公眾號:前端先鋒歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章 sh...
摘要:控制臺將顯示回調(diào)地獄通常,回調(diào)只能由一個(gè)異步函數(shù)調(diào)用。更多資源使更友好規(guī)范使用異步函數(shù)簡化異步編碼旅程異步編程是一項(xiàng)在中無法避免的挑戰(zhàn)。 JavaScript經(jīng)常聲稱是_異步_。那是什么意思?它如何影響發(fā)展?近年來這種方法有何變化? 請思考以下代碼: result1 = doSomething1(); result2 = doSomething2(result1); 大多數(shù)語言都處理每...
摘要:控制臺將顯示回調(diào)地獄通常,回調(diào)只能由一個(gè)異步函數(shù)調(diào)用。更多資源使更友好規(guī)范使用異步函數(shù)簡化異步編碼旅程異步編程是一項(xiàng)在中無法避免的挑戰(zhàn)。 JavaScript經(jīng)常聲稱是_異步_。那是什么意思?它如何影響發(fā)展?近年來這種方法有何變化? 請思考以下代碼: result1 = doSomething1(); result2 = doSomething2(result1); 大多數(shù)語言都處理每...
閱讀 1523·2021-11-18 10:02
閱讀 1665·2021-09-04 16:40
閱讀 3175·2021-09-01 10:48
閱讀 876·2019-08-30 15:55
閱讀 1854·2019-08-30 15:55
閱讀 1372·2019-08-30 13:05
閱讀 3016·2019-08-30 12:52
閱讀 1628·2019-08-30 11:24