JavaScript異步編程之Promise的初步使用詳解
Promise對象是ES6提出的的異步編程的規(guī)范。說到異步編程,就不得不說說同步和異步這兩個概念。
從字面意思理解同步編程的話,似乎指的是兩個任務(wù)同步運行,如果這樣理解就錯了(至少筆者再沒有接觸到這個概念的時候有這種誤解)。同步和異步指的是代碼指定執(zhí)行的順序(結(jié)構(gòu)化編程范式的執(zhí)行順序總是由上至下,由前往后的),如果執(zhí)行的順序與代碼的相同,就是同步;如果不同,就是異步。
最初,操作系統(tǒng)都是基于命令行的,所有的的語言設(shè)計出來也天然是同步的語句,在這種情況下,也不需要異步編程。但是很快,圖形操作界面就出來了,所有的程序設(shè)計語言都不得不跟GUI打交道了。我們必須了解的是,GUI程序是一個不停繪制的界面程序:
while(done){ dosomething(); drawGUI();}
如果每個循環(huán)中執(zhí)行的任務(wù)dosomething()的事件太長,就會導(dǎo)致界面遲遲得不到繪制命令,直觀的表現(xiàn)就是卡頓。為了解決這個問題,使用JavaScript作為腳本的瀏覽器一般都會采用事件循環(huán)(Event Loop)的機制:
將耗時的行為規(guī)定為事件,事件與響應(yīng)回調(diào)函數(shù)綁定。 每個循環(huán),優(yōu)先處理同步代碼。 同步代碼完成,按照先后順序遍歷事件。 在剩下的沒有同步代碼的循環(huán)中,依次執(zhí)行事件的相應(yīng)函數(shù)。這樣,在單線程的情況下,就修改了任務(wù)的執(zhí)行順序,實現(xiàn)了異步的機制。因為同步的行為總是很快完成及時進行了界面繪制,界面卡頓的現(xiàn)象也大為改善了。
事件循環(huán)機制將UI設(shè)備的輸入輸出規(guī)定為事件,實際上,耗時的行為非常多,但是一般都與IO相關(guān),與IO相關(guān)的行為,JavaScript都提供了異步行為的代碼。例如,這里要用的一個加載圖片的實例。
2. 詳論首先準(zhǔn)備一個HTML頁面PromiseTest.html,在這個HTML頁面中加載JS的腳本PromiseTest.js:
<!DOCTYPE html><html><head> <meta charset='utf-8'> <script src='http://m.b3g6.com/bcjs/3rdParty/jquery-3.5.1.js'></script> <title>樣例</title></head><body> <div id = 'container'> </div> <script src='http://m.b3g6.com/bcjs/PromiseTest.js'></script></body></html>
原生的JS的圖像對象Image,是通過事件的形式來實現(xiàn)圖像的異步加載的:
$(function () {var img = new Image(); img.onload = function () { $(img).appendTo($(’#container’)); }; img.src = 'http://m.b3g6.com/bcjs/img.jpg'; });
為Image的事件句柄onload,添加一個相應(yīng)函數(shù),當(dāng)圖像裝載完成之后,就將裝載好的Image添加到HTML頁面的某個div元素子節(jié)點下。通過瀏覽器打開這個頁面,會直接顯示對應(yīng)地址的圖片。
這個JS腳本當(dāng)然也可以通過Promise來改寫:
$(function () {function getImg(uri){return new Promise(function(resolve, reject){ var img = new Image(); img.onload = function () {resolve(img); }; img.onerror = function () {reject(Error('Load Image Error!')); } img.src = uri;}); } var imgUri = './img.jpg'; getImg(imgUri).then(function(img){$(img).appendTo($(’#container’)); }, function(error){console.error('Failed!', error); })});
粗看起來,使用Promise,似乎使得程序顯得更加復(fù)雜和繁復(fù)了。但是我們要深入理解Promise機制的內(nèi)涵,這樣設(shè)計并不是為了好玩。
Promise對象代表的是一個預(yù)定要做、但是還未開始做的行為。既然是一個行為,當(dāng)然得進行計劃,并對行為結(jié)果做出規(guī)定:如果成功了,就執(zhí)行resolve;如果失敗了,就執(zhí)行reject。一般我們可以定義一個function,并且返回一個Promise對象。 調(diào)用返回Promise對象的function,這樣這個想要進行的行為就真正啟動了。不過resolve和reject只是兩個回調(diào)函數(shù),那么就通過then方法來規(guī)定成功和失敗對應(yīng)的真正的處理函數(shù)。可以看到,這樣的設(shè)計看起來很繁復(fù),但是卻很像是一個同步行為:規(guī)定一個未完成行為對象,行為完成了如何處理,行為失敗了又如何處理。而這也是Promise的目的:使得異步操作更像是一個同步的行為。
3. 參考同步(Synchronous)和異步(Asynchronous)
簡述JS單線程異步實現(xiàn)原理
JavaScript 運行機制詳解:再談Event Loop
到此這篇關(guān)于JavaScript異步編程之Promise的初步使用的文章就介紹到這了,更多相關(guān)js Promise使用內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. PHP laravel實現(xiàn)導(dǎo)出PDF功能2. python中文本字符處理的簡單方法記錄3. JS中6個對象數(shù)組去重的方法4. Python-openpyxl表格讀取寫入的案例詳解5. 使用Blazor框架實現(xiàn)在前端瀏覽器中導(dǎo)入和導(dǎo)出Excel6. 資深程序員:給Python軟件開發(fā)測試的25個忠告!7. vscode運行php報錯php?not?found解決辦法8. ASP基礎(chǔ)知識Command對象講解9. JavaScript實現(xiàn)留言板實戰(zhàn)案例10. Python使用Selenium自動進行百度搜索的實現(xiàn)

網(wǎng)公網(wǎng)安備