摘要:那么如何使用它呢請看下面例子我是寫在異步操作之后的操作總結通過控制臺打印的內容可以看出,跟使用回調函數在結果上并沒有什么異同。
今天我想說說說promise對象,說到這個對象就不能不提提異步操作,那么什么是異步操作,什么又是同步操作?
同步與異步操作區別同步操作的意思是在我們執行某個耗時比較長的操作的時候,下面的代碼就會等待上面的代碼執行完畢然后執行。說白了代碼是順序往下執行,某些操作執行的時間順序和代碼所在的行的順序是相同的。請看下面獲取一個txt文件的例子。
同步程序示例
首先,我們利用node先搭建一個服務器環境,默認獲取1.html靜態文件。代碼如下:
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...")
我們要從服務器用ajax獲取txt文本數據。然后從客戶端獲取數據,如果這個操作是一個同步操作。如下所示
客戶端獲取數據代碼
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("我是獲取文件之后執行的代碼");
結果如下:
等這個獲取文件這個操作執行完后,就會順序執行接下來的代碼。
這樣的操作有什么問題呢?如果這個獲取文件的代碼耗時比較長,我們的程序就會卡死,下面的代碼就不會執行下去,必須等獲取文件代碼執行完畢,解決問題的方法就是異步獲取文件。那么什么是異步操作呢?說白了就是把獲取文件的操作掛到另外一個線程,先執行后面的代碼,上面的獲取文件代碼不會阻塞下面代碼的運行。這兩個操作是同時進行的。在以前,通常,如果是異步獲取數據的,那么執行這個費時的獲取數據操作時,會指定一個回調函數,當獲取文件成功時觸發處理結果的回調函數。在這個過程中,下面其他的代碼會同時進行。把剛才獲取文件的代碼改成異步,請看下面代碼。
異步獲取數據程序示例
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("我是獲取文件后執行的代碼");
![圖片描述][2]
可以看出先執行了下面的代碼然后執行了ajax獲取文件回調函數里面的代碼,證明了下面的其他操作的代碼會與獲取文件操作同時執行。這就是異步操作與同步操作的區別
promise對象有什么用處?由上面示例可以看到如果是一個異步操作的代碼,通常,我們就需要為它指定回調函數,例如上面的代碼回調函數就是onreadystatechange當它的狀態碼變成4,收到服務器響應,我們拿到數據后再執行下步操作,先把它掛起來,讓下面的的代碼運行。但是如果因果關系變得復雜,回調事件變得很多,我們的代碼就會變得十分像一個向右的金字塔結構不利于閱讀。
promise對象巧妙的解決了這個問題,把回調函數變成了鏈式調用,更加符合代碼書寫習慣。那么如何使用它呢?
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("我是寫在異步操作之后的操作")
總結
通過控制臺打印的內容可以看出,跟使用回調函數在結果上并沒有什么異同。但是代碼結構更加清晰化,并且可以catch到錯誤信息。
1.先new 一個promise對象,然后給它的參數傳遞一個回調函數進去,回調函數里面有兩個參數resolve,reject都是函數。
2.resolve函數是把異步狀態變成成功,可以把異步結果作為它的參數傳遞到then的回調函數參數中,而then方法會在promise狀態成功時候調用;3.reject函數可以把promise狀態變成失敗,當異步請求狀態失敗時調用,可以傳遞出去錯誤信息,這個會觸發promise對象上的catch方法,通過promise對象的catch方法的回調函數的參數捕獲該錯誤信息。最后返回該promise對象實現鏈式調用。這就是promise對象的基本用法。
4.當然它還有all, race,resolve,reject等各種實例方法和靜態方法,不過上面的用法時最經常見到的,最基礎的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/83195.html
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。寫一個符合規范并可配合使用的寫一個符合規范并可配合使用的理解的工作原理采用回調函數來處理異步編程。 JavaScript怎么使用循環代替(異步)遞歸 問題描述 在開發過程中,遇到一個需求:在系統初始化時通過http獲取一個第三方服務器端的列表,第三方服務器提供了一個接口,可通過...
摘要:引擎線程也稱為內核,負責處理腳本程序例如引擎引擎線程負責解析腳本,運行代碼。對象代表一個未完成但預計將來會完成的操作。注意一旦新建就會立即執行它屬于,無法取消。 寫在前面: 第一遍學Promise時, 只是大概過了一遍, 感覺學的不夠深入, 這一篇算是對之前的一個總結吧. Promise在ES6中也屬于一個較難理解的一部分; 所以在學習一個比較難理解的知識點時, 我們可以圍繞這個知識點...
摘要:單線程就意味著,所有任務需要排隊,前一個任務結束,才會執行后一個任務。這決定了它只能是單線程,否則會帶來很復雜的同步問題。小結本身是單線程的,并沒有異步的特性。當異步函數執行時,回調函數會被壓入這個隊列。 走在前端的大道上 本篇將自己讀過的相關 js異步 的文章中,對自己有啟發的章節片段總結在這(會對原文進行刪改),會不斷豐富提煉總結更新。 概念 JS 是單線程的語言。 單線程就意味著...
摘要:單線程什么是單線程語言的執行環境是單線程所謂單線程,就是指一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成,再執行后面一個任務,以此類推。 單線程 什么是單線程? Javascript語言的執行環境是單線程(single thread) 所謂單線程,就是指一次只能完成一件任務。 如果有多個任務,就必須排隊,前面一個任務完成,再執行后面一個任務,以此類推。 執行JS代...
摘要:則是把類似的異步處理對象和處理規則進行規范化,并按照采用統一的接口來編寫,而采取規定方法之外的寫法都會出錯。這個對象有一個方法,指定回調函數,用于在異步操作執行完后執行回調函數處理。到目前為止,已經學習了創建對象和用,方法來注冊回調函數。 Promise 本文從js的異步處理出發,引入Promise的概念,并且介紹Promise對象以及其API方法。 js里的異步處理 可以參考這篇文章...
閱讀 2128·2021-09-27 14:04
閱讀 1873·2019-08-30 15:55
閱讀 1698·2019-08-30 13:13
閱讀 1065·2019-08-30 13:07
閱讀 2742·2019-08-29 15:20
閱讀 3240·2019-08-29 12:42
閱讀 3324·2019-08-28 17:58
閱讀 3593·2019-08-28 17:56