摘要:那么如何使用它呢請(qǐng)看下面例子我是寫在異步操作之后的操作總結(jié)通過(guò)控制臺(tái)打印的內(nèi)容可以看出,跟使用回調(diào)函數(shù)在結(jié)果上并沒有什么異同。
今天我想說(shuō)說(shuō)說(shuō)promise對(duì)象,說(shuō)到這個(gè)對(duì)象就不能不提提異步操作,那么什么是異步操作,什么又是同步操作?
同步與異步操作區(qū)別同步操作的意思是在我們執(zhí)行某個(gè)耗時(shí)比較長(zhǎng)的操作的時(shí)候,下面的代碼就會(huì)等待上面的代碼執(zhí)行完畢然后執(zhí)行。說(shuō)白了代碼是順序往下執(zhí)行,某些操作執(zhí)行的時(shí)間順序和代碼所在的行的順序是相同的。請(qǐng)看下面獲取一個(gè)txt文件的例子。
同步程序示例
首先,我們利用node先搭建一個(gè)服務(wù)器環(huán)境,默認(rèn)獲取1.html靜態(tài)文件。代碼如下:
let http = require("http"); let url = require("url"); let path = require("path"); let fs = require("fs"); http.createServer((req, res) => { var pathname = __dirname + url.parse(req.url).pathname; if (path.extname(pathname) === "") { pathname += "/"; } if (pathname.charAt(pathname.length - 1) === "/") { pathname += "1.html" } fs.exists(pathname, exists => { if (exists) { switch (path.extname(pathname)) { case ".html": res.writeHead(200, { "Content-type": "text/html" }); break; case ".js": res.writeHead(200, { "Content-type": "text/javascript" }); break; case ".jpg": res.writeHead(200, { "Content-type": "image/jpeg" }); break; case ".png": res.writeHead(200, { "Content-type": "image/png" }); case ".txt": res.writeHead(200, { "Content-type": "text/plain" }); break; case ".css": res.writeHead(200, { "Content-type": "text/css" }); break; default: ead res.writHead(200, { "Content-type": "application/octet-stream" }) } fs.readFile(pathname, (err, data) => { if (err) { console.log("read file error"); } else res.end(data); }) } }) }).listen(3000); console.log("server is runing...")
我們要從服務(wù)器用ajax獲取txt文本數(shù)據(jù)。然后從客戶端獲取數(shù)據(jù),如果這個(gè)操作是一個(gè)同步操作。如下所示
客戶端獲取數(shù)據(jù)代碼
function showTxt(txt) { console.log(txt); } function getDocuments(url, cb) { let xhr = new XMLHttpRequest(); xhr.open("GET", url,false); xhr.send();、 cb(xhr.responseText); } getDocuments("1.txt", showTxt); console.log("我是獲取文件之后執(zhí)行的代碼");
結(jié)果如下:
等這個(gè)獲取文件這個(gè)操作執(zhí)行完后,就會(huì)順序執(zhí)行接下來(lái)的代碼。
這樣的操作有什么問題呢?如果這個(gè)獲取文件的代碼耗時(shí)比較長(zhǎng),我們的程序就會(huì)卡死,下面的代碼就不會(huì)執(zhí)行下去,必須等獲取文件代碼執(zhí)行完畢,解決問題的方法就是異步獲取文件。那么什么是異步操作呢?說(shuō)白了就是把獲取文件的操作掛到另外一個(gè)線程,先執(zhí)行后面的代碼,上面的獲取文件代碼不會(huì)阻塞下面代碼的運(yùn)行。這兩個(gè)操作是同時(shí)進(jìn)行的。在以前,通常,如果是異步獲取數(shù)據(jù)的,那么執(zhí)行這個(gè)費(fèi)時(shí)的獲取數(shù)據(jù)操作時(shí),會(huì)指定一個(gè)回調(diào)函數(shù),當(dāng)獲取文件成功時(shí)觸發(fā)處理結(jié)果的回調(diào)函數(shù)。在這個(gè)過(guò)程中,下面其他的代碼會(huì)同時(shí)進(jìn)行。把剛才獲取文件的代碼改成異步,請(qǐng)看下面代碼。
異步獲取數(shù)據(jù)程序示例
function showTxt(txt) { console.log(txt); } function getDocuments(url, cb) { let xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.send(); xhr.onreadystatechange = () => { if (xhr.status === 200 && xhr.readyState == 4) { cb(xhr.responseText); } else if (xhr.readyState === 4 && xhr.status !== 200) { console.log(`${xhr.status}get error`); } }; } getDocuments("1.txt", showTxt); console.log("我是獲取文件后執(zhí)行的代碼");
![圖片描述][2]
可以看出先執(zhí)行了下面的代碼然后執(zhí)行了ajax獲取文件回調(diào)函數(shù)里面的代碼,證明了下面的其他操作的代碼會(huì)與獲取文件操作同時(shí)執(zhí)行。這就是異步操作與同步操作的區(qū)別
promise對(duì)象有什么用處?由上面示例可以看到如果是一個(gè)異步操作的代碼,通常,我們就需要為它指定回調(diào)函數(shù),例如上面的代碼回調(diào)函數(shù)就是onreadystatechange當(dāng)它的狀態(tài)碼變成4,收到服務(wù)器響應(yīng),我們拿到數(shù)據(jù)后再執(zhí)行下步操作,先把它掛起來(lái),讓下面的的代碼運(yùn)行。但是如果因果關(guān)系變得復(fù)雜,回調(diào)事件變得很多,我們的代碼就會(huì)變得十分像一個(gè)向右的金字塔結(jié)構(gòu)不利于閱讀。
promise對(duì)象巧妙的解決了這個(gè)問題,把回調(diào)函數(shù)變成了鏈?zhǔn)秸{(diào)用,更加符合代碼書寫習(xí)慣。那么如何使用它呢?
function getTxt(url) { let p = new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.send(); xhr.onreadystatechange = () => { if (xhr.readyState !== 4) { return; } if (xhr.status === 200) { resolve(xhr.responseText); } else { reject(`${xhr.status}get error`); } } }); return p; } getTxt("1.txt").then(showTxt).catch((error) => { console.log(error); }); console.log("我是寫在異步操作之后的操作")
總結(jié)
通過(guò)控制臺(tái)打印的內(nèi)容可以看出,跟使用回調(diào)函數(shù)在結(jié)果上并沒有什么異同。但是代碼結(jié)構(gòu)更加清晰化,并且可以catch到錯(cuò)誤信息。
1.先new 一個(gè)promise對(duì)象,然后給它的參數(shù)傳遞一個(gè)回調(diào)函數(shù)進(jìn)去,回調(diào)函數(shù)里面有兩個(gè)參數(shù)resolve,reject都是函數(shù)。
2.resolve函數(shù)是把異步狀態(tài)變成成功,可以把異步結(jié)果作為它的參數(shù)傳遞到then的回調(diào)函數(shù)參數(shù)中,而then方法會(huì)在promise狀態(tài)成功時(shí)候調(diào)用;3.reject函數(shù)可以把promise狀態(tài)變成失敗,當(dāng)異步請(qǐng)求狀態(tài)失敗時(shí)調(diào)用,可以傳遞出去錯(cuò)誤信息,這個(gè)會(huì)觸發(fā)promise對(duì)象上的catch方法,通過(guò)promise對(duì)象的catch方法的回調(diào)函數(shù)的參數(shù)捕獲該錯(cuò)誤信息。最后返回該promise對(duì)象實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用。這就是promise對(duì)象的基本用法。
4.當(dāng)然它還有all, race,resolve,reject等各種實(shí)例方法和靜態(tài)方法,不過(guò)上面的用法時(shí)最經(jīng)常見到的,最基礎(chǔ)的。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/83195.html
摘要:從最開始的到封裝后的都在試圖解決異步編程過(guò)程中的問題。為了讓編程更美好,我們就需要引入來(lái)降低異步編程的復(fù)雜性。寫一個(gè)符合規(guī)范并可配合使用的寫一個(gè)符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來(lái)處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過(guò)程中,遇到一個(gè)需求:在系統(tǒng)初始化時(shí)通過(guò)http獲取一個(gè)第三方服務(wù)器端的列表,第三方服務(wù)器提供了一個(gè)接口,可通過(guò)...
摘要:引擎線程也稱為內(nèi)核,負(fù)責(zé)處理腳本程序例如引擎引擎線程負(fù)責(zé)解析腳本,運(yùn)行代碼。對(duì)象代表一個(gè)未完成但預(yù)計(jì)將來(lái)會(huì)完成的操作。注意一旦新建就會(huì)立即執(zhí)行它屬于,無(wú)法取消。 寫在前面: 第一遍學(xué)Promise時(shí), 只是大概過(guò)了一遍, 感覺學(xué)的不夠深入, 這一篇算是對(duì)之前的一個(gè)總結(jié)吧. Promise在ES6中也屬于一個(gè)較難理解的一部分; 所以在學(xué)習(xí)一個(gè)比較難理解的知識(shí)點(diǎn)時(shí), 我們可以圍繞這個(gè)知識(shí)點(diǎn)...
摘要:?jiǎn)尉€程就意味著,所有任務(wù)需要排隊(duì),前一個(gè)任務(wù)結(jié)束,才會(huì)執(zhí)行后一個(gè)任務(wù)。這決定了它只能是單線程,否則會(huì)帶來(lái)很復(fù)雜的同步問題。小結(jié)本身是單線程的,并沒有異步的特性。當(dāng)異步函數(shù)執(zhí)行時(shí),回調(diào)函數(shù)會(huì)被壓入這個(gè)隊(duì)列。 走在前端的大道上 本篇將自己讀過(guò)的相關(guān) js異步 的文章中,對(duì)自己有啟發(fā)的章節(jié)片段總結(jié)在這(會(huì)對(duì)原文進(jìn)行刪改),會(huì)不斷豐富提煉總結(jié)更新。 概念 JS 是單線程的語(yǔ)言。 單線程就意味著...
摘要:?jiǎn)尉€程什么是單線程語(yǔ)言的執(zhí)行環(huán)境是單線程所謂單線程,就是指一次只能完成一件任務(wù)。如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再執(zhí)行后面一個(gè)任務(wù),以此類推。 單線程 什么是單線程? Javascript語(yǔ)言的執(zhí)行環(huán)境是單線程(single thread) 所謂單線程,就是指一次只能完成一件任務(wù)。 如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再執(zhí)行后面一個(gè)任務(wù),以此類推。 執(zhí)行JS代...
摘要:則是把類似的異步處理對(duì)象和處理規(guī)則進(jìn)行規(guī)范化,并按照采用統(tǒng)一的接口來(lái)編寫,而采取規(guī)定方法之外的寫法都會(huì)出錯(cuò)。這個(gè)對(duì)象有一個(gè)方法,指定回調(diào)函數(shù),用于在異步操作執(zhí)行完后執(zhí)行回調(diào)函數(shù)處理。到目前為止,已經(jīng)學(xué)習(xí)了創(chuàng)建對(duì)象和用,方法來(lái)注冊(cè)回調(diào)函數(shù)。 Promise 本文從js的異步處理出發(fā),引入Promise的概念,并且介紹Promise對(duì)象以及其API方法。 js里的異步處理 可以參考這篇文章...
閱讀 2138·2021-09-27 14:04
閱讀 1883·2019-08-30 15:55
閱讀 1707·2019-08-30 13:13
閱讀 1076·2019-08-30 13:07
閱讀 2754·2019-08-29 15:20
閱讀 3247·2019-08-29 12:42
閱讀 3345·2019-08-28 17:58
閱讀 3606·2019-08-28 17:56