一文帶你詳細(xì)拆解JavaScript中Promise的原理和真實(shí)應(yīng)用
我一直覺得 Promise 最大的理解障礙不是技術(shù),而是命名。.then 這個(gè)詞太抽象了——“然后”?然后什么?然后就完了?但如果你把它翻譯成中文的**“等”**,一切就清晰了。
promise.then(fn) → promise.等(fn)
等還沒有結(jié)果。等完了,然后呢?還需要繼續(xù)等嗎?
再看 Promise 這個(gè)詞本身——承諾。
“我承諾幫你干這件事,事情被包在承諾里,你就等著,干完了叫你。”
一個(gè)"承諾",一個(gè)"等",就是 Promise 全部的秘密。
本文從中文語義出發(fā),逐層深入到 .then 源碼、resolve 與 then 的聯(lián)動(dòng)機(jī)制、await 的編譯真相,最后用一道面試實(shí)戰(zhàn)題把所有知識(shí)串起來。讀完之后,Promise 對(duì)你來說不再是一個(gè)需要記憶的 API,而是一個(gè)可以用直覺推導(dǎo)的思維模型。
一、承諾:Promise 的中文本義
Promise 翻譯成中文就是承諾。而且這個(gè)詞和 Promise 的語義幾乎完美對(duì)應(yīng):
“我承諾給你一個(gè)結(jié)果,但不是現(xiàn)在。”
const 承諾 = fetch('/api');
// 我承諾會(huì)給你數(shù)據(jù),但現(xiàn)在還沒拿到
// 你先拿著這個(gè)"承諾",等我兌現(xiàn)
Promise 的三種狀態(tài)用"承諾"來理解天然成立:
pending → 承諾還沒兌現(xiàn),等著
fulfilled → 承諾兌現(xiàn)了,拿到了結(jié)果
rejected → 承諾違約了,出錯(cuò)了
resolve 和 reject 也可以直接翻譯:
new Promise((兌現(xiàn), 違約) => {
if (成功) 兌現(xiàn)(結(jié)果); // 信守承諾
else 違約(錯(cuò)誤); // 承諾作廢
});
而整個(gè) Promise 機(jī)制,就是三個(gè)角色的協(xié)作:
承諾人(executor): 我來干活
等待人(.then): 我等著,干完了叫我
結(jié)果(resolve 的值):干完的交付物
我承諾幫你干,你就等著,干完了叫你。 這就是 Promise 的全部。
二、用"等"重新理解.then鏈
先看一段最普通的 Promise 代碼:
fetch('/api')
.then(data => parse(data))
.then(result => save(result))
.then(() => console.log('完成'));
現(xiàn)在把 .then 替換成"等":
發(fā)請(qǐng)求
.等(數(shù)據(jù)回來了 → 解析)
.等(解析完了 → 保存)
.等(保存完了 → 打印"完成")
讀起來是不是像說人話了?每個(gè)"等"都在問同一個(gè)問題:
- 等什么? → 等上一步完成
- 等到了,拿到什么? → 上一步的結(jié)果
- 等完之后呢? → 看你的回調(diào)返回什么,可能還要繼續(xù)等
最后一點(diǎn)最關(guān)鍵——等完了可能還要等。這就是 Promise 鏈能無限串下去的原因。
而鏈?zhǔn)秸{(diào)用就是承諾的傳遞:
A 承諾:我?guī)湍隳脭?shù)據(jù) → 你等
A 兌現(xiàn)了,你拿到數(shù)據(jù)
B 承諾:我?guī)湍憬馕鲞@個(gè)數(shù)據(jù) → 你等
B 兌現(xiàn)了,你拿到解析結(jié)果
C 承諾:我?guī)湍愦娴綌?shù)據(jù)庫 → 你等
C 兌現(xiàn)了,完事
每一步干完活的人說"我搞定了",下一個(gè)人才開始干。活是一個(gè)一個(gè)承諾出去的,你就一個(gè)一個(gè)等。
三、"等"的三種結(jié)局
當(dāng)"等"到了上一步的結(jié)果,你的回調(diào)函數(shù)執(zhí)行了,它的返回值決定了下一個(gè)"等"的命運(yùn):
結(jié)局一:返回一個(gè)普通值 → 等到了,立刻交付
promise.等(data => {
return data + 1; // 返回普通值 2
});
// 下一個(gè)"等"立刻拿到 2,不用真的等
結(jié)局二:返回一個(gè)新的 Promise → 還得繼續(xù)等
promise.等(data => {
return fetch('/api2'); // 返回新的 Promise(新承諾)
});
// 下一個(gè)"等"被鎖住了,要等 fetch 完成才能繼續(xù)
結(jié)局三:不返回任何值 → 等到了個(gè)寂寞
promise.等(data => {
console.log(data); // 用了,但沒 return
});
// 下一個(gè)"等"拿到 undefined,值斷了
結(jié)局二是整個(gè) Promise 機(jī)制最核心的特性。 正是因?yàn)?quot;等完了還可以繼續(xù)等",才讓異步操作能像水管一樣串聯(lián)起來。
四、從源碼看"等"的實(shí)現(xiàn)
下面是一個(gè)簡化但忠實(shí)于 Promise/A+ 規(guī)范的實(shí)現(xiàn)。我在關(guān)鍵位置標(biāo)注了"等"和"承諾"的語義:
class MyPromise {
constructor(executor) {
this.status = 'pending'; // 承諾還沒兌現(xiàn)
this.value = undefined; // 兌現(xiàn)后的結(jié)果
this.callbacks = []; // 排隊(duì)等的人
const resolve = (value) => {
if (this.status !== 'pending') return;
this.status = 'fulfilled'; // 承諾兌現(xiàn)了!
this.value = value;
this.callbacks.forEach(cb => this._handle(cb)); // 通知所有排隊(duì)的人
};
executor(resolve); // 把"兌現(xiàn)"的能力交給承諾人
}
then(onFulfilled) {
// ★ 每次"等",都會(huì)產(chǎn)生一個(gè)新的"承諾"
let resolve2;
const 新承諾 = new MyPromise((resolve) => {
resolve2 = resolve; // 把新承諾的兌現(xiàn)開關(guān)拿出來,先不按
});
const callback = { onFulfilled, resolve2 };
if (this.status === 'fulfilled') {
this._handle(callback); // 承諾已兌現(xiàn),直接處理
} else {
this.callbacks.push(callback); // 還沒兌現(xiàn),留個(gè)電話等通知
}
return 新承諾; // 返回的永遠(yuǎn)是一個(gè)新的承諾,不是具體的值
}
_handle({ onFulfilled, resolve2 }) {
queueMicrotask(() => {
const result = onFulfilled(this.value);
if (result instanceof MyPromise) {
// ★ 等到的結(jié)果還是一個(gè)承諾 → 把自己的開關(guān)交出去
result.then(resolve2);
} else {
// ★ 等到的是一個(gè)確切的值 → 直接按下開關(guān)
resolve2(result);
}
});
}
}
整個(gè)源碼的核心邏輯用"等"和"承諾"來概括就一句話:
承諾兌現(xiàn)了,看結(jié)果是不是還是一個(gè)承諾。是 → 繼續(xù)等;不是 → 交付。
五、resolve和.then是怎么聯(lián)動(dòng)的
看完源碼結(jié)構(gòu),一個(gè)最關(guān)鍵的問題浮出水面:resolve 寫在 constructor 里,.then 寫在外面,它們互不知道對(duì)方什么時(shí)候執(zhí)行。那結(jié)果是怎么傳遞過去的?
答案是 this.callbacks 這個(gè)數(shù)組——它是 resolve 和 .then 之間的橋梁。
callbacks(共享的信箱)
│
┌────────┴────────┐
│ │
resolve .then
(承諾人) (等待人)
│ │
"我干完了, "我來等結(jié)果,
看看有沒有人等著" 看看是不是已經(jīng)干完了"
誰先誰后?兩種情況都能處理。
情況一:先.then,后resolve(最常見)
const p = new Promise((resolve) => {
setTimeout(() => resolve('hello'), 1000);
});
p.then(value => console.log(value));
時(shí)刻 0ms:
.then 執(zhí)行,發(fā)現(xiàn) status 是 pending
→ 把 { onFulfilled, resolve2 } 存進(jìn) callbacks
→ 就像留了個(gè)電話號(hào)碼:"兌現(xiàn)了打這個(gè)號(hào)通知我"
時(shí)刻 1000ms:
resolve('hello') 被調(diào)用
→ status 改為 fulfilled,value 存為 'hello'
→ 遍歷 callbacks,逐個(gè)調(diào) _handle
→ onFulfilled('hello') 執(zhí)行
先留電話,活干完了打電話通知。
情況二:先resolve,后.then
const p = Promise.resolve('hello');
p.then(value => console.log(value));
.then 執(zhí)行,發(fā)現(xiàn) status 已經(jīng)是 fulfilled
→ 不存 callbacks,直接調(diào) _handle
→ onFulfilled('hello') 執(zhí)行
到了才發(fā)現(xiàn)活早干完了,結(jié)果就在柜臺(tái)上,直接拿走。
兩邊各自只關(guān)心自己的事,但合在一起恰好覆蓋了所有時(shí)序可能:
resolve 的邏輯:
"我干完了"
→ 改 status,存 value
→ callbacks 里有人嗎?有就逐個(gè)通知,沒有就算了(值存著,誰來都能拿)
.then 的邏輯:
"我來等"
→ status 是 fulfilled 嗎?
→ 是 → 直接拿值走人
→ 不是 → 把自己塞進(jìn) callbacks,等著被叫
這個(gè)設(shè)計(jì)還有一個(gè)精妙的約束——狀態(tài)不可逆:
const resolve = (value) => {
if (this.status !== 'pending') return; // 兌現(xiàn)過了就不能再變
};
pending → fulfilled ? 可以 fulfilled → pending ? 不行
一旦承諾兌現(xiàn)就永遠(yuǎn)是兌現(xiàn)的,結(jié)果永久緩存在 this.value 里。不管多少個(gè) .then 來,拿到的都是同一個(gè)結(jié)果,不會(huì)過期。普通的發(fā)布-訂閱(EventEmitter)做不到這一點(diǎn)——事件觸發(fā)了你沒監(jiān)聽就錯(cuò)過了。但承諾不會(huì),承諾兌現(xiàn)了就是兌現(xiàn)了,什么時(shí)候來取都行。
六、result.then(resolve2)—— 把自己的命運(yùn)交給別人
源碼中最精妙的一行:
_handle({ onFulfilled, resolve2 }) {
queueMicrotask(() => {
const result = onFulfilled(this.value);
if (result instanceof MyPromise) {
result.then(resolve2); // 這一行
} else {
resolve2(result);
}
});
}
resolve2 是誰的?是"新承諾"(.then 返回的那個(gè) Promise)的兌現(xiàn)開關(guān)。正常情況下,這個(gè)開關(guān)應(yīng)該由 _handle 自己按下。但當(dāng) result 是一個(gè) Promise 時(shí):
result.then(resolve2);
翻譯成中文:
嘿 result,我不按這個(gè)開關(guān)了。
你什么時(shí)候兌現(xiàn)了承諾,你幫我按。
你兌現(xiàn)了什么值,那就是我的值。
這就是控制權(quán)轉(zhuǎn)移——新承諾把自己的命運(yùn)鎖定到了 result 身上。
對(duì)比兩個(gè)分支:
resolve2(result); // 自己按開關(guān):我等到了確切的值,直接交付 result.then(resolve2); // 把開關(guān)交給別人:我等到的還是一個(gè)承諾,讓它來決定我的命運(yùn)
用生活場景打比方:
你去餐廳點(diǎn)了菜(發(fā)起 .then)
服務(wù)員給你一個(gè)取餐號(hào)(返回新的 Promise)
情況一:菜做好了,直接上桌
→ resolve2(菜),你吃上了
情況二:服務(wù)員說"這道菜的食材要等隔壁店送來"
→ 服務(wù)員把你的取餐號(hào)轉(zhuǎn)給了隔壁店
→ 隔壁店送到了 → 你的號(hào)才被叫到
→ result.then(resolve2)
七、new Promise()vs.then()—— 自己承諾 vs 被安排的承諾
// 自己承諾:你完全控制什么時(shí)候兌現(xiàn)
const a = new Promise((resolve) => {
setTimeout(() => resolve('hello'), 1000);
// 你自己決定 1 秒后兌現(xiàn)承諾
});
// 被安排的承諾:你控制不了
const b = a.then(value => {
return value + ' world';
});
// b 什么時(shí)候兌現(xiàn),取決于 a 什么時(shí)候兌現(xiàn)
// 以及你的回調(diào)返回的是值還是新的承諾
而且 .then() 返回的永遠(yuǎn)是一個(gè)新的承諾,不是具體的值:
const a = Promise.resolve(1); const b = a.then(v => v + 1); // b 是承諾,不是 2 const c = a.then(v => 'hello'); // c 是承諾,不是 'hello' const d = a.then(v => undefined); // d 是承諾,不是 undefined
因?yàn)?.then 的第一件事就是 new 一個(gè)新的 Promise 然后 return 它。你的回調(diào)返回值只決定了這個(gè)承諾以什么值兌現(xiàn),而不是替代承諾本身。
這也是 .then 能無限鏈下去的原因——每一步返回的都是承諾,承諾就有 .等 方法。如果返回的是 2,那 2.等(fn) 就報(bào)錯(cuò)了,鏈直接斷了。
八、等到了個(gè)寂寞:不返回值的陷阱
大多數(shù)人這樣寫 .then:
fetch('/api').then(data => {
console.log(data); // 用了,但沒 return
});
回到源碼,沒有 return 意味著 result = undefined:
_handle({ onFulfilled, resolve2 }) {
const result = onFulfilled(this.value);
// ↑ 沒有 return,result 是 undefined
if (result instanceof MyPromise) {
result.then(resolve2); // 走不到這里
} else {
resolve2(result); // resolve2(undefined)
}
}
下一個(gè)"等"等到了 undefined——承諾倒是兌現(xiàn)了,但兌現(xiàn)了個(gè)寂寞。
fetch('/api')
.等(data => {
console.log(data); // 有值
// 沒有 return
})
.等(result => {
console.log(result); // undefined,值斷了
});
很多人覺得沒問題,因?yàn)楹竺鏇]人接了。但這說明他們把 .then 當(dāng)成了事件監(jiān)聽器,而不是管道變換器——上一節(jié)的輸出應(yīng)該是下一節(jié)的輸入。
在實(shí)際代碼里,這個(gè)細(xì)節(jié)也很致命:
chain.then(() => promise) // ? 箭頭函數(shù)隱式 return promise
chain.then(() => { promise }) // ? 花括號(hào),沒 return,等了個(gè)寂寞,鏈直接穿透
只差一對(duì)花括號(hào),一個(gè)是"等到了還要繼續(xù)等",一個(gè)是"承諾兌現(xiàn)了個(gè)空氣"。
九、await—— 讓你假裝不用等的語法糖
幻覺
async function foo() {
const value = await somePromise;
console.log(value); // 看起來直接拿到了值
}
真相
function foo() {
return somePromise.等(value => {
console.log(value); // 值還是在回調(diào)參數(shù)里
});
}
await 做的事情就是讓編譯器幫你把函數(shù)劈開——遇到 await 就是一刀,后半部分整個(gè)塞進(jìn) .then 的回調(diào)里:
async function foo() {
// -------- 第一半:同步執(zhí)行 --------
console.log('開始');
const value = await somePromise;
// -------- 第二半:塞進(jìn) .then 回調(diào) --------
console.log(value);
return value + 1;
}
// 編譯器翻譯后:
function foo() {
console.log('開始');
return somePromise.then(value => {
console.log(value);
return value + 1;
});
}
多個(gè) await 就是多次劈開:
async function foo() {
const a = await p1; // 第一刀
const b = await p2; // 第二刀
return a + b;
}
// 等價(jià)于:
function foo() {
return p1.等(a => {
return p2.等(b => {
return a + b;
});
});
}
值永遠(yuǎn)在回調(diào)里,從來沒有"逃出"過
如果你追問:那外面怎么拿到 a + b 的?
const c = await foo();
展開:
foo().等(c => {
// c 在回調(diào)參數(shù)里
});
再往外套一層?
async function outer() {
const result = await main();
}
// 展開:
main().等(result => { ... });
一直追到調(diào)用棧最頂層:
main(); // 返回 Promise,沒人再 await 它了
值從來沒有被賦值給回調(diào)外部的任何變量。 它只是從一個(gè)"等"的回調(diào)參數(shù),傳到下一個(gè)"等"的回調(diào)參數(shù),一路傳下去。
所以 const c = await foo() 不是"賦值",是傳參。resolve(a + b) 把值傳給了 .then(c => ...) 的參數(shù) c。await 只是讓這個(gè)參數(shù)看起來像是賦值給了一個(gè)局部變量。
await 沒有發(fā)明任何新的取值方式,它只是讓你不用手寫嵌套的"等"了。你每次寫下 await,其實(shí)都是在說:“我先等等。” 只不過編譯器替你排好了隊(duì),讓你以為自己沒在等而已。
十、實(shí)戰(zhàn):并行執(zhí)行,串行輸出
理解了"承諾"和"等",來看一道面試級(jí)別的問題:
實(shí)現(xiàn)一個(gè)隊(duì)列,任務(wù) push 時(shí)立即執(zhí)行(并行),但結(jié)果按 push 順序輸出(串行)。
function createQueue(onResult) {
let 等待鏈 = Promise.resolve(); // 初始:一個(gè)已經(jīng)兌現(xiàn)的承諾
return {
push(task) {
const promise = task(); // 立即執(zhí)行(并行)
等待鏈 = 等待鏈
.等(() => promise) // 等上一個(gè)輸出完 → 返回當(dāng)前任務(wù)的承諾 → 繼續(xù)等
.等(onResult); // 等任務(wù)兌現(xiàn) → 輸出結(jié)果
},
done() {
return 等待鏈;
}
};
}
用"等"來讀這段代碼:
push(A):
等待鏈(已兌現(xiàn))
.等(→ promiseA) // 不用等,直接執(zhí)行,但返回了 promiseA → 要等它兌現(xiàn)
.等(onResult) // 等 A 兌現(xiàn) → 輸出 A
push(B):
等待鏈(現(xiàn)在是 A 的輸出承諾)
.等(→ promiseB) // A 還沒輸出完,這個(gè)回調(diào)還不執(zhí)行
.等(onResult) // 等 B 兌現(xiàn) → 輸出 B
push(C):
等待鏈(現(xiàn)在是 B 的輸出承諾)
.等(→ promiseC) // B 還沒輸出完,繼續(xù)排隊(duì)等
.等(onResult) // 等 C 兌現(xiàn) → 輸出 C
關(guān)鍵洞察:任務(wù)在 push 時(shí)就已經(jīng)開始執(zhí)行了(并行),但"等"鏈保證了結(jié)果按順序釋放。等鏈輪到某個(gè)任務(wù)時(shí),它的承諾可能早就兌現(xiàn)了,那就直接通過,不浪費(fèi)時(shí)間。
"等"不一定真的要花時(shí)間等。它只保證了順序,而沒有犧牲并行性。
就像你同時(shí)找了三個(gè)人幫忙,但跟他們說:
"你們仨同時(shí)干,但交活的時(shí)候排好隊(duì), A 先交,B 再交,C 最后交, 別管誰先干完,順序不能亂。"
干活并行,交活串行。承諾的"等"就是這個(gè)排隊(duì)交活的機(jī)制。
完整測試:
function delay(ms, value) {
return () => new Promise(resolve => {
console.log(`[啟動(dòng)] ${value}`);
setTimeout(() => resolve(value), ms);
});
}
const results = [];
const queue = createQueue(result => {
results.push(result);
console.log(`[輸出] ${result}`);
});
queue.push(delay(300, 'A')); // 最慢
queue.push(delay(200, 'B'));
queue.push(delay(100, 'C')); // 最快
queue.done().then(() => {
console.log(results);
// [啟動(dòng)] A
// [啟動(dòng)] B ← 三個(gè)同時(shí)啟動(dòng)
// [啟動(dòng)] C
// [輸出] A ← 但輸出嚴(yán)格按順序
// [輸出] B
// [輸出] C
});
C 最先完成,但它要等 A 和 B 先輸出。A 最慢,但它排第一個(gè),不用等任何人。
十一、更高的視角:類是維度的上升
回過頭來看 Promise 的設(shè)計(jì)——resolve 寫在 constructor 里,.then 寫在方法里,兩邊互不知道對(duì)方什么時(shí)候執(zhí)行。但它們通過 status + callbacks 這兩個(gè)共享狀態(tài),無論誰先誰后,結(jié)果都對(duì)。
平時(shí)我們寫代碼,都是在單一時(shí)間線上思考:
// 我是發(fā)送方,我只管發(fā)
socket.send(data);
// 我是接收方,我只管收
socket.onmessage = (data) => { ... };
這兩段代碼各管各的,它們之間的協(xié)調(diào)要靠開發(fā)者自己在腦子里對(duì)齊時(shí)序。
但 Promise 做了什么?把兩條時(shí)間線折疊進(jìn)一個(gè)對(duì)象里:
const p = new Promise((resolve) => {
// 時(shí)間線 A:發(fā)送/生產(chǎn) —— 承諾人
干活(結(jié)果 => resolve(結(jié)果));
});
p.then(結(jié)果 => {
// 時(shí)間線 B:接收/消費(fèi) —— 等待人
});
兩條原本獨(dú)立的時(shí)間線,通過 new Promise() 這個(gè)"高維容器"被收納到了同一個(gè)實(shí)體里。它們在時(shí)間上可能相隔很久,但在邏輯上被綁定在了一起。
這個(gè)模式不只在 Promise 里,到處都是:
Promise: 封裝了"兌現(xiàn)承諾"和"等待承諾"兩條時(shí)間線
EventEmitter: 封裝了"發(fā)事件"和"收事件"兩條時(shí)間線
Redux Store: 封裝了"寫狀態(tài)"和"讀狀態(tài)"兩條時(shí)間線
數(shù)據(jù)庫事務(wù): 封裝了"多個(gè)操作"和"成功/回滾"兩條時(shí)間線
每一個(gè)都是同樣的模式——把多個(gè)可能發(fā)生在不同時(shí)刻的邏輯,折疊進(jìn)一個(gè)高維容器里統(tǒng)一管理。
所以類的封裝,不只是"把數(shù)據(jù)和方法放在一起"這么簡單。它真正的價(jià)值是維度的上升:
將不同時(shí)間維度上的邏輯,收納進(jìn)同一個(gè)空間維度的實(shí)體里,讓它們能夠協(xié)作。
Promise 管理的是"承諾與兌現(xiàn)"的關(guān)系,EventEmitter 管理的是"發(fā)布與訂閱"的關(guān)系,事務(wù)管理的是"操作與一致性"的關(guān)系。好的類設(shè)計(jì)讓人覺得"優(yōu)雅",正是因?yàn)樗皇窃诮鉀Q當(dāng)下這一刻的問題,而是在管理一段跨越時(shí)間的關(guān)系。
下次設(shè)計(jì)一個(gè)類的時(shí)候,可以問自己一個(gè)問題:
“我是在封裝數(shù)據(jù),還是在折疊時(shí)間線?”
如果是后者,你大概率在做真正有價(jià)值的抽象。
十二、總結(jié)
| 概念 | 用"承諾"和"等"來理解 |
|---|---|
| new Promise(executor) | 我承諾幫你干這件事,executor 里就是要干的活 |
| resolve(value) | 承諾兌現(xiàn)了,交付結(jié)果 |
| reject(error) | 承諾違約了,告知原因 |
| .then(fn) | 等承諾兌現(xiàn),然后執(zhí)行 fn |
| .then 的返回值 | 永遠(yuǎn)是一個(gè)新的承諾,不是具體的值 |
| fn 返回普通值 | 新承諾立刻兌現(xiàn) |
| fn 返回 Promise | 新承諾鎖定到返回的 Promise,繼續(xù)等 |
| fn 不返回值 | 新承諾兌現(xiàn)了個(gè)寂寞(undefined) |
| callbacks 數(shù)組 | resolve 和 .then 的聯(lián)動(dòng)橋梁——先到的留電話,后到的查結(jié)果 |
| 狀態(tài)不可逆 | 承諾兌現(xiàn)了就是兌現(xiàn)了,什么時(shí)候來取都行 |
| await | 編譯器幫你把函數(shù)劈開,后半部分塞進(jìn) .then 的回調(diào)里 |
| await 的值 | 從來沒有"逃出"回調(diào),只是從一個(gè)"等"傳到下一個(gè)"等" |
| 并行執(zhí)行串行輸出 | 活同時(shí)干,但承諾排著隊(duì)兌現(xiàn) |
| 類的本質(zhì) | 維度的上升——把多條時(shí)間線折疊進(jìn)一個(gè)對(duì)象里 |
如果 JavaScript 是中國人發(fā)明的,Promise 一定叫"承諾",.then 一定叫 .等,resolve 一定叫"兌現(xiàn)",reject 一定叫"違約"。
而你每次寫下 await,其實(shí)都是在說:“我先等等。”
只不過編譯器替你排好了隊(duì),讓你以為自己沒在等而已。
以上就是一文帶你詳細(xì)拆解JavaScript中Promise的原理和真實(shí)應(yīng)用的詳細(xì)內(nèi)容,更多關(guān)于JavaScript Promise原理與應(yīng)用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序天氣預(yù)報(bào)功能實(shí)現(xiàn)(支持自動(dòng)定位,附源碼)
對(duì)于一個(gè)經(jīng)常出門在外的人,關(guān)注天氣是至關(guān)重要的,下面這篇文章主要給大家介紹了關(guān)于微信小程序天氣預(yù)報(bào)功能實(shí)現(xiàn)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),支持自動(dòng)定位,需要的朋友可以參考下2022-04-04
javascript游戲開發(fā)之《三國志曹操傳》零部件開發(fā)(四)用地圖塊拼成大地圖
小時(shí)候我們玩過拼圖游戲,是用自己的手去拼的。今天我們來研究研究用javascript來拼圖感興趣的朋友可以了解下,希望本文對(duì)你有所幫助2013-01-01
php register_shutdown_function函數(shù)詳解
register_shutdown_function() 函數(shù)可實(shí)現(xiàn)當(dāng)程序執(zhí)行完成后執(zhí)行的函數(shù),其功能為可實(shí)現(xiàn)程序執(zhí)行完成的后續(xù)操作,需要的朋友可以參考下2017-07-07
微信小程序scroll-view實(shí)現(xiàn)滾動(dòng)到錨點(diǎn)左側(cè)導(dǎo)航欄點(diǎn)餐功能(點(diǎn)擊種類,滾動(dòng)到錨點(diǎn))
這篇文章主要介紹了微信小程序scroll-view左側(cè)導(dǎo)航欄點(diǎn)餐功能實(shí)現(xiàn),點(diǎn)擊種類,滾動(dòng)到錨點(diǎn);滾動(dòng)到錨點(diǎn),種類選中,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
微信開發(fā) js實(shí)現(xiàn)tabs選項(xiàng)卡效果
這篇文章主要介紹了微信開發(fā)的學(xué)習(xí)筆記,js實(shí)現(xiàn)tabs選項(xiàng)卡效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
JS實(shí)現(xiàn)登錄頁面記住密碼和enter鍵登錄方法推薦
下面小編就為大家?guī)硪黄狫S實(shí)現(xiàn)登錄頁面記住密碼和enter鍵登錄方法推薦。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。2016-05-05

