JavaScript異步編程之Promise的初步使用詳解
1. 概述
Promise對(duì)象是ES6提出的的異步編程的規(guī)范。說到異步編程,就不得不說說同步和異步這兩個(gè)概念。
從字面意思理解同步編程的話,似乎指的是兩個(gè)任務(wù)同步運(yùn)行,如果這樣理解就錯(cuò)了(至少筆者再?zèng)]有接觸到這個(gè)概念的時(shí)候有這種誤解)。同步和異步指的是代碼指定執(zhí)行的順序(結(jié)構(gòu)化編程范式的執(zhí)行順序總是由上至下,由前往后的),如果執(zhí)行的順序與代碼的相同,就是同步;如果不同,就是異步。
最初,操作系統(tǒng)都是基于命令行的,所有的的語言設(shè)計(jì)出來也天然是同步的語句,在這種情況下,也不需要異步編程。但是很快,圖形操作界面就出來了,所有的程序設(shè)計(jì)語言都不得不跟GUI打交道了。我們必須了解的是,GUI程序是一個(gè)不停繪制的界面程序:
while(done)
{
dosomething();
drawGUI();
}
如果每個(gè)循環(huán)中執(zhí)行的任務(wù)dosomething()的事件太長(zhǎng),就會(huì)導(dǎo)致界面遲遲得不到繪制命令,直觀的表現(xiàn)就是卡頓。為了解決這個(gè)問題,使用JavaScript作為腳本的瀏覽器一般都會(huì)采用事件循環(huán)(Event Loop)的機(jī)制:
- 將耗時(shí)的行為規(guī)定為事件,事件與響應(yīng)回調(diào)函數(shù)綁定。
- 每個(gè)循環(huán),優(yōu)先處理同步代碼。
- 同步代碼完成,按照先后順序遍歷事件。
- 在剩下的沒有同步代碼的循環(huán)中,依次執(zhí)行事件的相應(yīng)函數(shù)。
這樣,在單線程的情況下,就修改了任務(wù)的執(zhí)行順序,實(shí)現(xiàn)了異步的機(jī)制。因?yàn)橥降男袨榭偸呛芸焱瓿杉皶r(shí)進(jìn)行了界面繪制,界面卡頓的現(xiàn)象也大為改善了。
事件循環(huán)機(jī)制將UI設(shè)備的輸入輸出規(guī)定為事件,實(shí)際上,耗時(shí)的行為非常多,但是一般都與IO相關(guān),與IO相關(guān)的行為,JavaScript都提供了異步行為的代碼。例如,這里要用的一個(gè)加載圖片的實(shí)例。
2. 詳論
首先準(zhǔn)備一個(gè)HTML頁面PromiseTest.html,在這個(gè)HTML頁面中加載JS的腳本PromiseTest.js:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="./3rdParty/jquery-3.5.1.js"></script>
<title>樣例</title>
</head>
<body>
<div id = "container"> </div>
<script src="./PromiseTest.js"></script>
</body>
</html>
原生的JS的圖像對(duì)象Image,是通過事件的形式來實(shí)現(xiàn)圖像的異步加載的:
$(function () {
var img = new Image();
img.onload = function () {
$(img).appendTo($('#container'));
};
img.src = "./img.jpg";
});
為Image的事件句柄onload,添加一個(gè)相應(yīng)函數(shù),當(dāng)圖像裝載完成之后,就將裝載好的Image添加到HTML頁面的某個(gè)div元素子節(jié)點(diǎn)下。通過瀏覽器打開這個(gè)頁面,會(huì)直接顯示對(duì)應(yīng)地址的圖片。
這個(gè)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機(jī)制的內(nèi)涵,這樣設(shè)計(jì)并不是為了好玩。
- Promise對(duì)象代表的是一個(gè)預(yù)定要做、但是還未開始做的行為。既然是一個(gè)行為,當(dāng)然得進(jìn)行計(jì)劃,并對(duì)行為結(jié)果做出規(guī)定:如果成功了,就執(zhí)行resolve;如果失敗了,就執(zhí)行reject。一般我們可以定義一個(gè)function,并且返回一個(gè)Promise對(duì)象。
- 調(diào)用返回Promise對(duì)象的function,這樣這個(gè)想要進(jìn)行的行為就真正啟動(dòng)了。不過resolve和reject只是兩個(gè)回調(diào)函數(shù),那么就通過then方法來規(guī)定成功和失敗對(duì)應(yīng)的真正的處理函數(shù)。
可以看到,這樣的設(shè)計(jì)看起來很繁復(fù),但是卻很像是一個(gè)同步行為:規(guī)定一個(gè)未完成行為對(duì)象,行為完成了如何處理,行為失敗了又如何處理。而這也是Promise的目的:使得異步操作更像是一個(gè)同步的行為。
3. 參考
同步(Synchronous)和異步(Asynchronous)
簡(jiǎn)述JS單線程異步實(shí)現(xiàn)原理
JavaScript 運(yùn)行機(jī)制詳解:再談Event Loop
到此這篇關(guān)于JavaScript異步編程之Promise的初步使用的文章就介紹到這了,更多相關(guān)js Promise使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js模仿windows桌面圖標(biāo)排列算法具體實(shí)現(xiàn)(附圖)
需要引入Jquery,如果需要全部功能,請(qǐng)引入jquery-ui和jquery-ui.css,具體實(shí)現(xiàn)步驟如下,感興趣的朋友可以參考下哈2013-06-06
使用Echarts設(shè)置地圖并觸發(fā)點(diǎn)擊事件的代碼
這篇文章主要給大家介紹了關(guān)于使用Echarts設(shè)置地圖并觸發(fā)點(diǎn)擊事件的的相關(guān)資料,ECharts是一款基于JavaScript的數(shù)據(jù)可視化庫,可以用于創(chuàng)建各種類型的交互式圖表,包括地圖,需要的朋友可以參考下2023-09-09
javascript setTimeout和setInterval計(jì)時(shí)的區(qū)別詳解
window對(duì)象有兩個(gè)主要的定時(shí)方法,分別是setTimeout 和 setInteval 他們的語法基本上相同,但是完成的功能取有區(qū)別。2013-06-06
javascript數(shù)組遍歷for與for in區(qū)別詳解
這篇文章主要介紹了javascript數(shù)組遍歷for與for in區(qū)別,是篇非常不錯(cuò)的文章,這里推薦給小伙伴們。2014-12-12
微信小程序?qū)崿F(xiàn)MUI數(shù)字輸入框效果
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)MUI數(shù)字輸入框效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
PHP中使用微秒計(jì)算腳本執(zhí)行時(shí)間例子
這篇文章主要介紹了PHP中使用微秒計(jì)算腳本執(zhí)行時(shí)間例子,本文先是講解了microtime函數(shù)的一些知識(shí),然后給出了一個(gè)計(jì)算腳本運(yùn)行時(shí)間的類,需要的朋友可以參考下2014-11-11
javascript實(shí)現(xiàn)自動(dòng)填寫表單實(shí)例簡(jiǎn)析
這篇文章主要介紹了javascript實(shí)現(xiàn)自動(dòng)填寫表單的方法,以一個(gè)簡(jiǎn)單實(shí)例形式分析了JavaScript結(jié)合瀏覽器設(shè)置實(shí)現(xiàn)自動(dòng)保存表單的相關(guān)技巧,需要的朋友可以參考下2015-12-12
javascript自啟動(dòng)函數(shù)的問題探討
自啟動(dòng)函數(shù)想必大家并不陌生吧,在本文將為大家詳細(xì)探討下,感興趣的朋友可不要錯(cuò)過2013-10-10
javascript:文字不間斷向左移動(dòng)的實(shí)例代碼
這篇文章介紹了javascript:文字不間斷向左移動(dòng)的實(shí)例代碼,有需要的朋友可以參考一下2013-08-08

