1??網址里的 “搜索請求” 結構
這張圖是在教你怎么看懂?網址里的 “搜索請求” 結構,特別基礎但超重要,對你學前端幫別人做搜索功能超有用,用大白話拆成 3 步講:
1. 先看「協議(Protocol)」
HTTPS
?就是瀏覽器和服務器溝通的 “安全規矩”,保證你搜東西時,傳遞的內容(比如你搜啥關鍵詞)不會被別人偷偷看到、篡改,就像寄快遞用 “加密包裝”,安全送到。
2. 再看「服務器網址(Target)」
https://www.youtube.com/results
?是 YouTube 服務器里 “負責處理搜索” 的固定地址,相當于你想找 YouTube 要搜索結果,得先找到它家 “搜索部門” 的門牌號 。
3. 最后看「查詢參數(Query Params)」
search_query=web+lab
?是你給服務器的 “搜索指令” !search_query
?是規矩里的 “關鍵詞標簽”(告訴服務器這是搜索內容),web+lab
?是你實際想搜的內容(用?+
?代替空格,瀏覽器的小習慣)。服務器收到這個,就會返回和?web lab
?相關的 YouTube 視頻結果啦~
總結:整個網址就是讓瀏覽器帶著 “安全規矩”,拿著 “搜索部門地址”+“你要搜的內容”,去 YouTube 服務器要結果,就像你帶著 “暗號 + 地址 + 需求”,找朋友幫你找東西一樣 ,前端里做搜索功能,經常得這么拼網址、傳參數喲~
2??HTTP 請求的兩個關鍵組成部分
?
?HTTP 請求的兩個關鍵組成部分,是前端和服務器打交道的基礎,用大白話拆成兩部分講:
左邊「Request Headers(請求頭)」
- 作用:給服務器 “額外信息”,讓服務器更懂你的請求,比如:
Host
:告訴服務器你要訪問哪個域名(比如?developer.mozilla.org
?),防止服務器 confused;User-Agent
:說明 “你用啥瀏覽器、啥系統”(比如 “Firefox/50.0” ),服務器知道后,能給你返回適配你瀏覽器的頁面;Accept
:告訴服務器 “你能看懂啥格式的內容”(比如要 HTML 網頁、JSON 數據 ),方便服務器給你對應的數據;
簡單說就是:給請求加 “背景信息”,讓服務器更貼心回應你,所以 PPT 里說 “fancy stuff(花里胡哨但有用的細節)”~
右邊「Request Body(請求體)」
- 作用:存 “請求的核心數據”,常見于?
POST
?請求(比如注冊、提交表單 )。- 舉個栗子:注冊新用戶時,
Request Body
?里會裝 “用戶名、密碼、郵箱” 這些信息,服務器拿到后,就知道要新建一個用戶; - 格式:通常用?
JSON
(和 JavaScript 對象寫法很像 ),因為簡單、通用,服務器和前端都能看懂;
簡單說就是:** 存你要發給服務器的 “正經數據”,是請求的 “核心內容”**~
- 舉個栗子:注冊新用戶時,
總結一下:
你給服務器發請求時,請求頭(Headers)是 “輔助信息”(讓服務器了解你的環境、需求),請求體(Body)是 “核心數據”(你真正要提交給服務器的內容)。
前端寫登錄、注冊、提交表單,都會用到這倆,是和后端溝通的必備知識!
3 URL和路由
【什么叫URL啊,路由嗎?】。實在是很愚蠢的提問啊!
URL(Uniform Resource Locator)即統一資源定位符,它和路由有一定聯系,但并不完全等同。
URL
URL 是用來在互聯網上標識和定位資源的一種地址,就像是你在現實生活中要找某個地方需要知道它的具體地址一樣,在網絡里要獲取特定資源,就得通過 URL 。
一個完整的 URL 通常包含以下幾個部分 :
- 協議部分:常見的有?
http://
(超文本傳輸協議,用于普通網頁訪問)和?https://
(在?http
?基礎上增加了加密功能,用于安全的網頁訪問,比如涉及支付的頁面 ),它規定了瀏覽器和服務器之間如何傳輸數據。 - 域名部分:比如?
www.baidu.com
?,它對應著服務器在網絡中的地址,就像一個門牌號,瀏覽器根據它找到對應的服務器。 - 端口部分:如果不寫,通常會使用默認端口,比如?
http
?默認是 80 端口,https
?默認是 443 端口。特定服務可能會使用其他端口,比如 MySQL 數據庫默認 3306 端口。不過在日常訪問網頁時,默認端口一般省略不寫。 - 路徑部分:在服務器上定位具體資源的位置,例如?
https://www.example.com/blog/article1
?中,/blog/article1
?就表示在?example.com
?服務器上?blog
?目錄下的?article1
?這個資源。 - 查詢參數部分:以?
?
?開頭,后面是一些鍵值對,用于向服務器傳遞額外信息,比如?https://www.example.com/search?keyword=前端
?,keyword=前端
?就是查詢參數,告訴服務器要搜索和 “前端” 相關的內容。
路由
在 web 開發尤其是前端框架(比如 Vue Router、React Router)里,路由指的是根據不同的 URL 路徑,匹配并渲染對應的組件或頁面 。
- 前端路由:通過 JavaScript 監聽 URL 的變化(比如?
hash
?變化或者?history
?模式下的 URL 變化 ),然后動態地更新頁面內容,而不需要重新加載整個頁面。比如在單頁面應用(SPA)中,訪問?http://example.com/home
?和?http://example.com/about
?,頁面不會重新刷新,而是根據不同的路由規則,加載不同的組件展示內容。 - 后端路由:在后端服務器中,根據不同的 URL 路徑,匹配對應的處理函數或控制器。例如,在 Node.js 里使用 Express 框架,你可以定義?
app.get('/user', function(req, res) { /* 處理獲取用戶信息邏輯 */ })
?,當用戶訪問?http://yourserver.com/user
?時,就會執行對應的處理函數,返回相關數據。
兩者關系
可以把 URL 理解成一個大的標識,而路由是對 URL 中路徑部分進行解析和處理的一種機制。路由根據 URL 的路徑信息,決定采取什么樣的操作,比如展示哪個頁面、執行哪個后端邏輯 ,是對 URL 進行更細致的管理和響應。
4??HTTP 狀態碼(Status Codes)
1. 1xx( informational - 信息提示 )
- 作用:服務器已收到請求,告訴你 “正在處理,別著急”,實際開發中很少直接碰到,屬于 “中間狀態”。
- 例子:
100 Continue
(服務器說 “你繼續發數據,我準備好了” ),一般瀏覽器自動處理,用戶感知不到。
2. 2xx( you succeeded - 請求成功 )
- 作用:服務器說 “成了!你的請求我完美處理啦”,前端拿到這系列狀態碼,就可以開心渲染數據~
- 常用碼:
200 OK
(最常見,請求成功,服務器給你返回數據,比如頁面、接口數據 );201 Created
(一般用在新增數據,比如注冊用戶、發帖子成功,服務器 “創建資源成功” )。
3. 3xx( redirect - 重定向 )
- 作用:服務器說 “你要的東西不在這,我指引你去新地址找”,瀏覽器會自動跳轉到新地址。
- 常用碼:
301 Moved Permanently
(永久重定向,比如舊網址不用了,永久跳轉到新網址,搜索引擎會更新索引 );302 Found
(臨時重定向,比如維護時,臨時跳轉到備用頁面 );304 Not Modified
(資源沒變化,服務器讓瀏覽器直接用緩存,省流量 )。
4. 4xx( you did something wrong - 客戶端錯誤 )
- 作用:服務器說 “你發的請求有問題,我沒法處理”,大部分是前端 / 用戶的鍋(比如傳參錯、權限不夠 )。
- 常用碼:
400 Bad Request
(請求寫錯了,比如接口傳參格式不對,服務器看不懂 );401 Unauthorized
(沒權限,比如沒登錄就訪問需要登錄的頁面 / 接口 );403 Forbidden
(服務器認出你了,但就是不讓你訪問,比如權限不夠 );404 Not Found
(經典!要找的資源 / 頁面 / 接口不存在,比如輸錯網址 )。
5. 5xx( server did something wrong - 服務器錯誤 )
- 作用:服務器說 “哎呀,我內部出問題了,沒法處理你的請求”,是服務器的鍋(代碼 bug、服務器崩了 )。
- 常用碼:
500 Internal Server Error
(服務器內部報錯,比如代碼拋異常了 );502 Bad Gateway
(服務器當 “網關” 時出錯,比如反向代理、負載均衡環節出問題 );503 Service Unavailable
(服務器太忙 / 維護中,沒法響應,比如雙 11 搶購把服務器打崩 )。
一句話總結
- 1xx:“我收到了,處理中”
- 2xx:“成了!”
- 3xx:“去那邊找→”
- 4xx:“你發的請求有毛病!”
- 5xx:“我服務器炸了……”
開發時,遇到接口報錯,先看狀態碼屬于哪類,能快速定位問題(是自己傳參錯,還是服務器崩了 ),超有用!想深入學可以戳 PPT 里的鏈接 👉?HTTP Status Codes - REST API TutorialThis page is created from HTTP status code information found at ietf.org and Wikipedia.Click on the category heading or the status code link to read more.1xx Informational This class of status code indicates a provisional response, consisting only of the Status-Line and optional headers, and is terminated by an empty line. There are no required headers for this class of status code. Since `HTTP/1.0` did not define any `1xx` status codes, servers MUST NOT send a `1xx` response to an `HTTP/1.https://www.restapitutorial.com/httpstatuscodes.html?有更全的案例~
5??API(應用程序編程接口)
- 全稱:Application Program Interface(應用程序編程接口 )
- 作用:是一組 “端點(endpoint)”,允許你向某個服務發起請求,簡單說就是?“別人開放給你用的功能入口”?,比如想調用百度地圖、微信支付的功能,就通過它們的 API 對接。
- 實際案例:谷歌(Google)、亞馬遜(Amazon)、臉書(Facebook )等大公司,都會開放 API ,讓其他開發者 / 公司能借助它們的服務(比如用谷歌地圖 API 做地圖功能,用亞馬遜 API 對接云服務 )。
API 是 “別人做好的功能接口”,你不用自己從頭開發復雜功能,直接通過 API 調用別人的服務,省時省力。
6?調用外部 API 時 “API key/token 的作用和傳遞方式
【什么叫token?】
在 API 調用等場景中,token(令牌 )是一串用于身份驗證和授權的字符串,它就像是一把 “電子鑰匙”,作用如下:
身份驗證
當你通過 API 去訪問某個服務時,服務器需要確認你是否有資格使用該服務。
token 就用于證明你的身份,只有攜帶有效的 token,服務器才會認為你是經過授權的合法使用者。比如你想調用某天氣 API 獲取數據,就需要先在該 API 平臺注冊申請一個 token,每次請求時帶上這個 token,服務器驗證 token 有效,才會給你返回天氣數據 。
權限控制
不同的 token 可能對應不同的權限。例如,在一個用戶管理 API 中,普通用戶的 token 可能只能查看自己的信息,而管理員的 token 除了查看信息,還能進行用戶創建、刪除等操作 。
流量限制(rate limit)
一些 API 提供方會根據 token 來對使用者進行流量限制。比如,免費版的 token 可能限制每天只能調用 API 100 次,而付費版的 token 調用次數則會更多 。
傳輸位置
token 可以放在 HTTP 請求的不同位置,如查詢參數(query params)里,
像https://api.example.com/data?token=your_token_value
?;
也可以放在請求體(body)中,不過這種方式一般用于像 POST 請求提交表單數據等情況 ;
還能放在請求頭(header)里,
常見的寫法是Authorization: Bearer your_token_value
?,這是一種比較安全且常用的方式,
能避免 token 在 URL 中被輕易看到 。
1. API key/token 的核心作用
很多外部 API(比如地圖、天氣、支付接口 ),會要求你用?API key 或 token?,用來:
- 限流(rate limit):限制你 “調用 API 的頻率 / 次數”,防止你把人家服務器打崩,或者區分免費 / 付費用戶(比如免費用戶 1 天只能調 100 次,付費用戶能調 1 萬次 )。
- 計費(charge):記錄你用了多少 API 資源,按調用量收錢(類似 “你用多少流量,運營商收多少錢” )。
2. API key/token 的傳遞位置
拿到 key 或 token 后,你得在?HTTP 請求里帶上它,有 3 種常見 “放法”:
- Query Params(查詢參數):直接拼在 URL 里,像?
https://api.example.com/data?token=xxx
?,簡單但不太安全(別人能從 URL 看到 )。 - Body(請求體):把 key/token 放到請求體里(比如 POST 請求的表單、JSON 數據 ),適合傳大量數據時用。
- Header(請求頭):放在請求頭里(比如?
Authorization: Bearer xxx
?),相對安全、規范,很多 API 推薦這么傳。
總結:
調用外部 API 時,得用 key/token “證明身份 + 控制調用量 / 付費”,
而且要選一種方式(URL、請求體、請求頭 )把它傳給 API 服務器,人家才給你干活。
(簡單說就是:想用別人的 API ?先領 “身份憑證”,再按規矩把憑證放進請求里,不然不讓用 )
7?web里面的promise是什么?
在 Web 開發(尤其是 JavaScript)里,Promise
?是用來優雅處理異步操作的工具。
在 Web 開發中,尤其是 JavaScript 語言里,Promise
既不是單純的方法,也不是外部引入的庫 ,它是ES6(ECMAScript 2015)規范中新增的內置對象,用于更方便、優雅地處理異步操作。以下是詳細介紹:
你可以把它理解成一個 “承諾”:當你發起一個需要等待的操作(比如從服務器加載數據、讀取文件),Promise
?會先 “答應” 你,等這個操作完成后,一定會給你一個結果 —— 要么成功返回數據,要么告訴你失敗原因。
為什么需要 Promise?
沒有?Promise
?之前,處理多個異步操作可能會寫成 “嵌套的回調函數”,比如:
javascript
// 嵌套回調(回調地獄)
loadData1(function(data1) {loadData2(data1, function(data2) {loadData3(data2, function(data3) {// 更多嵌套...});});
});
這種代碼像 “金字塔” 一樣越來越深,可讀性差,不好維護。
Promise 怎么用?
Promise
?把異步操作包裝成一個對象,用鏈式調用替代嵌套,讓代碼更清晰。
基本用法:
javascript
// 1. 創建一個 Promise(表示一個異步操作)
const promise = new Promise((resolve, reject) => {// 模擬異步操作(比如從服務器請求數據)setTimeout(() => {const success = true; // 假設請求成功if (success) {resolve("拿到的數據:xxx"); // 成功時,用 resolve 返回結果} else {reject("出錯了:網絡故障"); // 失敗時,用 reject 返回原因}}, 1000);
});// 2. 處理結果(鏈式調用)
promise.then(result => {// 成功時執行(拿到 resolve 的結果)console.log("成功:", result);}).catch(error => {// 失敗時執行(拿到 reject 的原因)console.log("失敗:", error);}).finally(() => {// 無論成功/失敗,都會執行(比如關閉加載動畫)console.log("操作結束");});
核心特點:
-
三種狀態:
pending
(進行中):操作還沒完成;fulfilled
(已成功):操作完成,調用?resolve()
;rejected
(已失敗):操作出錯,調用?reject()
。
狀態一旦變化(從?pending
?到?fulfilled
?或?rejected
),就不會再變。
-
鏈式調用:
then()
?方法會返回一個新的?Promise
,所以可以一直?.then().then()
?下去,解決嵌套問題。 -
異步操作的 “容器”:
不管是網絡請求、定時器,還是其他異步操作,都能放進?Promise
?里統一管理。
簡單說:
Promise
?就像一個 “快遞單號”—— 你下單(發起異步操作)后,拿到單號(Promise
?對象),不用一直盯著,等快遞到了(操作完成),要么收到貨(resolve
),要么被告知丟件(reject
),整個過程不用 “死等”,代碼也更整潔。
前端開發中,調用 API 接口、處理文件上傳等場景,幾乎都會用到?Promise
?或基于它的?async/await
(更簡潔的語法)。
8?Promise 的執行順序、同步異步特性
核心是理解?“同步代碼立即執行,Promise 回調等同步代碼跑完后執行”,結合兩題(第11點)總結:
一、核心知識點(Promise 與同步代碼的執行順序)
JavaScript 執行代碼分「同步」和「異步」:
- 同步代碼:像?
console.log("Hi there!")
,會立即執行,優先跑完。 - 異步代碼:像?
promise.then(...)
?里的回調,會等同步代碼跑完后,再執行(即使 Promise 已經 resolve )。
二、結合兩題理解
題目 1(Promise reject 場景)
js
const f = (promise) => {promise.then(val => console.log("a")).then(val => console.log("b")).catch(err => console.log("error!"));
};
const promise = /* 一個會 reject 的 Promise */;
f(promise);
- 因為?
promise
?直接 reject,所以?.then
?不會執行,直接觸發?.catch
?→ 只打印?error!
題目 2(Promise resolve 場景 + 同步代碼)
js
const f = (promise) => {promise.then(val => console.log("a")).then(val => console.log("b")).catch(err => console.log("error!"));
};
const promise = /* 一個會 resolve 的 Promise */;
f(promise);
console.log("Hi there!"); // 同步代碼
- 執行順序:
- 同步代碼優先:先打印?
Hi there!
- 再執行 Promise 回調:
promise
?resolve 后,依次打印?a
?→?b
- 同步代碼優先:先打印?
三、總結規律
- Promise 狀態決定回調執行:
- resolve → 走?
.then
?鏈式調用; - reject → 跳過后續?
.then
,觸發最近的?.catch
。
- resolve → 走?
- 同步代碼 > 異步回調:
不管 Promise 多快 resolve,它的回調都會等同步代碼跑完才執行,這是 JavaScript “事件循環(Event Loop)” 的機制。
理解這兩點,就能看透 Promise 執行順序的題目啦~
9?.catch()
?就是 Promise 版的?try...catch
.catch()
?就是 Promise 版的?try...catch
,專門用來捕獲異步操作里的錯誤,給你拆分講透:
1. 和?try...catch
?像在哪?
-
try...catch
(同步代碼用):
寫同步代碼時,用?try
?包著可能出錯的代碼,catch
?抓錯誤:js
try {// 可能出錯的代碼(比如變量沒定義)console.log(xxx); } catch (err) {// 出錯了就執行這里,打印錯誤console.log('出錯啦:', err); }
-
.catch()
(Promise / 異步代碼用):
寫 Promise 異步操作時,用?.then()
?處理成功,.catch()
?抓 “異步操作里的錯誤”:js
?get("/api/stories").then((storyObjs) => {// 異步成功了,執行這里setStories(storyObjs); }).catch((err) => {// 異步出錯了(比如網絡斷了、服務器崩了),執行這里console.log("this is so sad: ", err.message); });
核心邏輯一樣:“試著執行代碼 → 出錯了就抓錯誤,別讓程序崩掉”,只是一個管同步,一個管異步~
2.?.catch()
?具體干啥?
- 時機:只有 Promise 走到?
rejected
?狀態(比如異步操作失敗、主動調用?reject()
?),才會觸發?.catch()
。 - 作用:
- 捕獲錯誤(比如網絡請求失敗、API 報錯 ),避免程序直接崩潰;
- 還能給用戶提示(比如 “網絡不好,刷新試試” ),或者記錄錯誤日志(方便開發排查問題 )。
3. 舉個真實例子對比
比如 “從服務器拿故事數據”:
-
用?
try...catch
(但它管不了異步!):
假設?get("/api/stories")
?是異步操作,try...catch
?抓不到異步錯誤,程序會直接崩:js
try {// 異步操作,try...catch 管不住!get("/api/stories").then((storyObjs) => { setStories(storyObjs);}); } catch (err) {// 這里永遠不會執行!因為異步錯誤沒被捕獲 console.log('抓不到異步錯誤'); }
-
用?
.catch()
(專門管異步錯誤):
換成?.catch()
,異步出錯就會被捕獲,程序能優雅提示:js
get("/api/stories").then((storyObjs) => {setStories(storyObjs);}).catch((err) => {// 異步出錯了,這里會執行!console.log("網絡崩了:", err.message); });
一句話總結
try...catch
?是同步代碼的 “安全網”,抓同步錯誤;.catch()
?是Promise 異步代碼的 “安全網”,抓異步錯誤。
你寫前端調接口時,只要用 Promise 做異步操作(比如?fetch
、axios
?),后面跟個?.catch()
,就能穩穩接住錯誤,超像?try...catch
?的異步版.
10?Promise 異步操作
【promise異步式編程其實就是多任務同時進行吧,類似于并發事件?】
Promise
?處理的異步操作和多任務同時進行(并發)有一定聯系,但并不完全等同 ,以下是具體區別:
從概念角度看
- Promise 異步操作:
Promise
?主要用于處理那些結果不是立即返回的操作,比如網絡請求(從服務器獲取數據)、讀取本地文件等。它強調的是對異步操作的結果進行管理,即操作完成后是成功還是失敗,并通過then()
方法處理成功結果,catch()
方法捕獲失敗情況。一個Promise
代表一個異步操作,但它本身并不意味著多個任務同時在執行。
舉個例子,使用Promise
發送兩個網絡請求:
javascript
function requestData1() {return new Promise((resolve, reject) => {setTimeout(() => {resolve('數據1');}, 1000);});
}function requestData2() {return new Promise((resolve, reject) => {setTimeout(() => {resolve('數據2');}, 1500);});
}requestData1().then(result1 => {console.log(result1);return requestData2();}).then(result2 => {console.log(result2);}).catch(error => {console.log(error);});
在這段代碼中,requestData1
和requestData2
兩個異步操作是順序執行的,requestData2
要等requestData1
成功執行完才會開始。
- 并發事件:指的是多個任務在同一時間點或同一時間段內同時執行。比如在操作系統中,多個進程或線程可以并發執行,它們利用多核 CPU 或者時間片輪轉等方式,讓用戶感覺多個任務好像是同時在運行。在瀏覽器環境中,Web Workers 可以實現真正意義上的多任務并發,它能開啟新的線程,讓一些計算密集型或耗時的任務在后臺運行,不影響主線程(負責頁面渲染和用戶交互)的操作,比如同時進行圖片處理和數據計算任務。
從實現機制角度看
-
Promise:基于 JavaScript 的事件循環機制。JavaScript 是單線程語言,沒有傳統意義上的多線程并發執行能力。事件循環會不斷檢查調用棧和任務隊列,當調用棧為空時,會從任務隊列中取出異步任務的回調放入調用棧執行。
Promise
?的異步操作也是通過事件循環來調度的,本質上是按照一定順序依次處理異步操作的結果,而不是真正的多任務同時運行。 -
并發:在多線程環境下,多個線程可以同時訪問 CPU 資源,并行執行不同的任務。在瀏覽器的 Web Workers 中,雖然也是單線程 JavaScript 環境,但它開辟了獨立于主線程的新線程,使得任務可以在不同線程中同時進行,實現了一定程度的并發效果。
從應用場景角度看
-
Promise:主要用于處理異步操作的先后順序,以及優雅地處理異步操作的成功和失敗情況。比如在前端開發中,按順序獲取用戶信息、用戶的訂單列表等,或者在調用多個 API 時,根據前一個 API 的返回結果決定是否調用下一個 API 。
-
并發:更適合處理那些可以并行執行,且不會相互干擾的任務,以提高執行效率。例如在大數據處理中,同時對多個數據塊進行計算分析;在游戲開發中,同時處理游戲畫面渲染和玩家輸入響應等任務。
雖然Promise
?本身不是多任務同時進行(并發),但它可以和其他技術(如 Web Workers)結合,在一定程度上實現更復雜的異步并發場景。
【然后每一個事件都有監聽嗎promise對應反饋,每一個“單子”都有一個記錄?】
可以把 Promise 理解成 “帶狀態追蹤的異步訂單系統”,用「訂單 + 監聽」的思路,給你拆解它的 “反饋記錄邏輯”,超適合新手理解:
1. 把 Promise 當 “異步訂單”
想象你在奶茶店點單:
- 下單(new Promise):你點了一杯奶茶(發起異步操作,比如?
fetch
?數據、setTimeout
?延遲任務 ),店員給你一個訂單號(Promise 對象),此時訂單狀態是「制作中(pending)」。 - 出餐(resolve/reject):
- 做好了(異步成功)→ 訂單狀態變成「已完成(fulfilled)」,還帶著 “奶茶(結果數據)”;
- 做砸了(異步失敗)→ 訂單狀態變成「已失敗(rejected)」,還帶著 “做錯的原因(錯誤信息)”。
2. “監聽反饋” 就像 “訂單通知”
你不用一直盯著做奶茶(不阻塞代碼),而是用?.then()
?/?.catch()
?訂閱 “訂單結果”:
.then()
:訂閱「訂單完成」的通知,拿到奶茶后執行 “喝奶茶(處理成功結果)”;.catch()
:訂閱「訂單失敗」的通知,知道做錯后執行 “換一杯(處理錯誤)”;
代碼里長這樣(對應奶茶訂單):
js
// 下單(發起異步操作)
const 奶茶訂單 = new Promise((resolve, reject) => {setTimeout(() => {const 做成功了 = true; if (做成功了) {// 出餐成功 → 標記訂單為「已完成」,附帶結果resolve("芋泥波波奶茶"); } else {// 出餐失敗 → 標記訂單為「已失敗」,附帶原因reject("芋泥沒有了"); }}, 1000); // 模擬做奶茶需要1秒
});// 監聽訂單結果:.then 收成功,.catch 收失敗
奶茶訂單.then(奶茶 => {console.log("拿到奶茶:", 奶茶); // 做成功時執行 → 拿到「芋泥波波奶茶」}).catch(錯誤原因 => {console.log("做砸了:", 錯誤原因); // 做失敗時執行 → 拿到「芋泥沒有了」});
3. 每個 “單子” 都有獨立記錄
- 訂單獨立:每個?
new Promise
?都是獨立訂單,互不干擾。比如同時點兩杯奶茶(兩個 Promise ),它們的制作狀態、結果會各自記錄,不會串單。 - 狀態不可逆:訂單一旦變成「已完成」或「已失敗」,狀態就固定了(比如做好的奶茶不會突然變成做錯,做錯的也沒法反悔 )。對應 Promise 的狀態一旦從?
pending
?變?fulfilled
/rejected
,就不會再變。
4. 和 “事件監聽” 的區別
雖然都有 “監聽反饋”,但 Promise 更簡單直接:
- 事件監聽(比如?
addEventListener
):可以反復觸發(比如按鈕點一次,監聽函數執行一次;再點,又執行 ),適合 “重復發生的事”(點擊、輸入 )。 - Promise:只觸發一次(訂單只完成 / 失敗一次 ),適合 “一次性的異步結果”(比如網絡請求、定時器 )。
一句話總結
Promise 就像 “帶狀態追蹤的一次性訂單”:
- 發起異步操作 = 下單,生成獨立 “訂單(Promise 對象)”;
resolve
/reject
?= 標記訂單結果(完成 / 失敗);.then()
/.catch()
?= 訂閱訂單結果的 “通知”,拿到結果后做后續操作。
每個 Promise 都像獨立的 “單子”,記錄自己的狀態和結果,保證異步操作的反饋清晰、不混亂~ 這樣理解后,再看代碼里的 Promise 鏈式調用、錯誤捕獲,就會覺得和 “訂單流程” 完全對應啦!
11?Promise 鏈式調用與錯誤捕獲
這是一道?Promise 鏈式調用與錯誤捕獲?的練習題,核心考察你對?Promise
?的?.then()
?鏈式調用、.catch()
?錯誤捕獲時機的理解,拆解一下:
1. 代碼邏輯梳理
- 前提:
promise
?是一個會 reject(失敗)的 Promise(比如網絡錯誤 )。 - 函數?
f
?的邏輯:
對?promise
?做鏈式調用:js
promise.then(val => console.log("a")) // ① 第一個 then.then(val => console.log("b")) // ② 第二個 then.catch(err => console.log("error!")); // ③ catch 捕獲錯誤
2. 關鍵:Promise 失敗時,鏈式調用如何執行?
- 因為?
promise
?一開始就?reject(失敗),所以:- 第一個?
.then(val => console.log("a"))
?不會執行(只有 Promise 成功時才會走?.then
?); - 錯誤會 “跳過” 前面的?
.then
,直接觸發?最近的?.catch
?。
- 第一個?
3. 執行結果推導
- 由于?
promise
?一開始就 reject,所以:- ① 和 ② 的?
.then
?都不執行(不會打印?a
、b
?); - 直接走到 ③ 的?
.catch
,打印?error!
?。
- ① 和 ② 的?
4. 答案
最終只會打印?error!
?,對應選項里的?“error!”?。
(本質是理解:Promise 一旦 reject,錯誤會在鏈式調用中 “冒泡”,跳過未執行的?.then
,直到被?.catch
?捕獲 )
?