ð¥ é¢è¯å®ïŒæå Promise å°è£ AJAXïŒè¿ 5 䞪èç¹ 90% ç人跪äºïŒ
åèšïŒåš AI çŒçšæ¶ä»£ïŒæå代ç èœåè¿æ¯å端工çšåžç"æ€åæ²³"åïŒæ¬æä»äžéçå®é¢è¯é¢åºåïŒåžŠäœ åœ»åºææ AJAXãFetchãPromiseãæ·±æ·èŽãå å管ç äºå€§æ žå¿èç¹ãææ«é宿Žä»£ç æš¡æ¿ïŒå»ºè®®æ¶èïŒ
ð ç®åœ
1. é¢è¯é¢åŒå
¥ïŒä» GitHub API è°çšè¯Žèµ·
2. AJAX vs FetchïŒæ¬èŽšåºå«äžåŒ åŸçæ
3. æå getJSONïŒPromise å°è£
AJAX 宿Žå®ç°
4. æå sleep åœæ°ïŒPromise åŒæ¥æ§å¶ç²Ÿé«
5. æ·±æ·èŽ vs æµ
æ·èŽïŒå
åæš¡åç»æè§£æ
6. é¢è¯é«é¢èç¹æ»ç» + ä»£ç æš¡æ¿
1ïžâ£ é¢è¯é¢åŒå ¥ïŒä» GitHub API è°çšè¯Žèµ·
å çäžæ®µ"æé®é¢"ç代ç ïŒäœ èœæŸåºå 䞪 bugïŒ
<script>
const members = document.querySelector('.member');
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.github.com/orgs/lemoncode/members", true);
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.status === 200 && xhr.readyState === 4){
const data = JSON.parse(xhr.responseText);
console.log(data);
}
}
// â èŽåœé误ïŒåšåè°å€è®¿é®åŒæ¥æ°æ®
const data = JSON.parse(xhr.responseText);
members.innerHTML = data.map(item => `<li>${item.login}</li>`).join("");
</script>
é误åæïŒ
| åºå· | é®é¢ | äž¥éæ§ |
|---|---|---|
| 1 | åŒæ¥æ¶åºé误ïŒåè°å€è®¿é® responseText | ðŽ èŽåœ |
| 2 | éæ©åšäžå¹é
ïŒ.member vs members | ðŽ èŽåœ |
| 3 | 猺å°é误å€ç | ð¡ äžç |
| 4 | åè°å°ç±é£é© | ð¡ äžç |
2ïžâ£ AJAX vs FetchïŒæ¬èŽšåºå«äžåŒ åŸçæ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â AJAX vs Fetch å¯¹æ¯ â
ââââââââââââââââââââ¬âââââââââââââââââââ¬ââââââââââââââââââââââââ€
â ç¹æ§ â AJAX â Fetch â
ââââââââââââââââââââŒâââââââââââââââââââŒââââââââââââââââââââââââ€
â åºäº â XMLHttpRequest â Promise â
â è¯æ³é£æ Œ â åè°åœæ° â then/catch/async-awaitâ
â 代ç å€æåºŠ â é« â äœ â
â é误å€ç â onerror çå¬ â catch æè· â
â é»è®€æºåžŠ cookie â æ¯ â åŠ (é credentials) â
â 请æ±äžæ¢ â abort() â AbortController â
â æµè§åšå
Œå®¹æ§ â IE8+ â IE äžæ¯æ â
ââââââââââââââââââââŽâââââââââââââââââââŽââââââââââââââââââââââââ
代ç 对æ¯
// â AJAX åæ³ïŒåè°é£æ ŒïŒ
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
// åµå¥åè°...
} else {
// é误å€ç
}
}
};
// â
Fetch åæ³ïŒPromise 飿 ŒïŒ
fetch(url)
.then(res => res.json())
.then(data => {
// å€çæ°æ®
})
.catch(err => {
// é误å€ç
});
3ïžâ£ æå getJSONïŒPromise å°è£ AJAX 宿Žå®ç°
é¢è¯èç¹
é¢è¯å®ïŒè¯·çš Promise å°è£ äžäžª getJSON åœæ°ïŒæ¯æ GET 请æ±ïŒè¿å JSON æ°æ®ã
宿Žå®ç°
/**
* æå getJSON åœæ° - Promise å°è£
AJAX
* @param {string} url - 请æ±å°å
* @returns {Promise} - è¿å Promise å®äŸ
*/
const getJSON = (url) => {
return new Promise((resolve, reject) => {
// 1. å建 XMLHttpRequest å®äŸ
const xhr = new XMLHttpRequest();
// 2. åå§å请æ±ïŒGET æ¹æ³ïŒåŒæ¥ïŒ
xhr.open('GET', url, true);
// 3. 讟眮请æ±å€ŽïŒå¯éïŒ
xhr.setRequestHeader('Content-Type', 'application/json');
// 4. åé请æ±
xhr.send();
// 5. çå¬ç¶æåå
xhr.onreadystatechange = function() {
// readyState 4 = 请æ±å®æ
if (xhr.readyState === 4) {
if (xhr.status === 200) {
try {
// è§£æ JSON æ°æ®
const data = JSON.parse(xhr.responseText);
// æåïŒè°çš resolve
resolve(data);
} catch (e) {
// JSON è§£æå€±èŽ¥
reject(new Error('JSON è§£æå€±èŽ¥: ' + e.message));
}
} else {
// HTTP ç¶æç é误
reject(new Error(`请æ±å€±èŽ¥ïŒç¶æç : ${xhr.status}`));
}
}
};
// 6. çå¬çœç»é误
xhr.onerror = function() {
reject(new Error('çœç»é误'));
};
// 7. çå¬è¶
æ¶ïŒå¯éïŒ
xhr.ontimeout = function() {
reject(new Error('请æ±è¶
æ¶'));
};
});
};
䜿çšç€ºäŸ
// éŸåŒè°çš
getJSON('https://api.github.com/orgs/lemoncode/members')
.then(data => {
console.log('æåå衚:', data);
return data[0]; // è¿å第äžäžªæå
})
.then(firstMember => {
console.log('第äžäžªæå:', firstMember.login);
})
.catch(err => {
console.error('é误:', err.message);
})
.finally(() => {
console.log('请æ±å®æïŒæ 论æå倱莥ïŒ');
});
// async/await åæ³ïŒæŽäŒé
ïŒ
async function fetchMembers() {
try {
const data = await getJSON('https://api.github.com/orgs/lemoncode/members');
console.log(data);
} catch (err) {
console.error(err);
} finally {
console.log('宿');
}
}
Promise ç¶ææµèœ¬åŸ
âââââââââââââââ
â PENDING â
â (çåŸ
äž) â
ââââââââ¬âââââââ
â
ââââââââââââââââŒâââââââââââââââ
â â â
⌠⌠âŒ
âââââââââââââââ âââââââââââââââ
â FULFILLED â â REJECTED â
â (æå) â â (倱莥) â
â then æ§è¡ â â catch æ§è¡ â
âââââââââââââââ âââââââââââââââ
4ïžâ£ æå sleep åœæ°ïŒPromise åŒæ¥æ§å¶ç²Ÿé«
é¢è¯èç¹
é¢è¯å®ïŒåŠäœçš Promise å®ç°äžäžª sleep åœæ°ïŒè®©ä»£ç "æå"æå®æ¶éŽïŒ
宿Žå®ç°
/**
* æå sleep åœæ°
* @param {number} ms - äŒç æ¯«ç§æ°
* @returns {Promise} - è¿å Promise å®äŸ
*/
function sleep(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
// æ¶éŽå°ïŒç¶æä» pending å䞺 fulfilled
resolve(`äŒç ${ms}ms 宿`);
}, ms);
});
}
䜿çšç€ºäŸ
// éŸåŒè°çš
sleep(1000)
.then(msg => {
console.log(msg); // 1 ç§åèŸåº
return sleep(2000);
})
.then(msg => {
console.log(msg); // å 2 ç§åèŸåº
});
// async/await åæ³ïŒæšèïŒ
async function run() {
console.log('åŒå§');
await sleep(1000);
console.log('1 ç§å');
await sleep(2000);
console.log('3 ç§å');
}
run();
â ïž åžžè§é误
// â é误ïŒåš setTimeout äžè°çš reject äœæ²¡ææä¹
function sleep(n) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(); // è¿äŒè®© Promise åäžºå€±èŽ¥ç¶æ
}, n);
});
}
// ç»æïŒäŒè§Šå catchïŒèäžæ¯ then
// â
æ£ç¡®ïŒåºè¯¥è°çš resolve
function sleep(n) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(); // æåç¶æ
}, n);
});
}
5ïžâ£ æ·±æ·èŽ vs æµ æ·èŽïŒå åæš¡åç»æè§£æ
JS å åæš¡å
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â JS å
åååž â
âââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââââ€
â æ å
å (Stack) â å å
å (Heap) â
âââââââââââââââââââââââââââŒââââââââââââââââââââââââââââââââââââ€
â ⢠ç®åæ°æ®ç±»å â â¢ å¯¹è±¡ãæ°ç»ãåœæ° â
â (number, string, â ⢠äžè¿ç»ååš â
â boolean, null, â ⢠éè¿åŒçšå°åè®¿é® â
â undefined, symbol) â ⢠ååŸåæ¶æºå¶ç®¡ç â
â ⢠è¿ç»ååšïŒè®¿é®å¿« â ⢠ååšå®é
æ°æ® â
â ⢠èªåšåé
éæŸ â â
âââââââââââââââââââââââââââŽââââââââââââââââââââââââââââââââââââ
æµ æ·èŽ vs æ·±æ·èŽ
const arr = [1, 2, { c: 3 }];
// æ¹æ³1ïŒconcat (æµ
æ·èŽ)
const arr1 = arr.concat([]);
arr1[2].c = 999;
console.log(arr[2].c); // 999 â åæ°ç»è¢«åœ±å
// æ¹æ³2ïŒJSON (æ·±æ·èŽïŒæå±é)
const arr2 = JSON.parse(JSON.stringify(arr));
arr2[2].c = 888;
console.log(arr[2].c); // 999 â
åæ°ç»äžå圱å
// æ¹æ³3ïŒstructuredClone (ç°ä»£æµè§åš)
const arr3 = structuredClone(arr);
// æ¹æ³4ïŒéåœå®ç° (宿޿·±æ·èŽ)
function deepClone(target, hash = new WeakMap()) {
if (target === null || typeof target !== 'object') return target;
if (hash.has(target)) return hash.get(target);
const clone = Array.isArray(target) ? [] : {};
hash.set(target, clone);
for (let key in target) {
if (target.hasOwnProperty(key)) {
clone[key] = deepClone(target[key], hash);
}
}
return clone;
}
æ¹æ³å¯¹æ¯è¡š
| æ¹æ³ | 埪ç¯åŒçš | Date | RegExp | Function | å Œå®¹æ§ |
|---|---|---|---|---|---|
concat/å±åŒ | â | â | â | â | â |
JSON | â | â ïž | â ïž | â | â |
structuredClone | â | â | â | â | â ïž |
| éåœå®ç° | â | â | â | â | â |
lodash.cloneDeep | â | â | â | â | â |
6ïžâ£ é¢è¯é«é¢èç¹æ»ç» + ä»£ç æš¡æ¿
ð æ žå¿èç¹æž å
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â åç«¯åŒæ¥çŒçšé¢è¯èç¹ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ€
â 1. AJAX åçïŒreadyStateãstatusãåè°æºå¶ â
â 2. Fetch APIïŒPromise åºç¡ãéŸåŒè°çšãé误å€ç â
â 3. Promise æåïŒç¶ææµèœ¬ãresolve/rejectãthen/catch â
â 4. async/awaitïŒè¯æ³ç³ãé误å€çãå¹¶è¡/äž²è¡æ§è¡ â
â 5. æ·±æ·èŽå®ç°ïŒéåœã埪ç¯åŒçšãç¹æ®ç±»åå€ç â
â 6. å
åæš¡åïŒæ /å åºå«ãåŒçšäŒ éãååŸåæ¶ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
ð¯ äžèœä»£ç æš¡æ¿
// ============ æš¡æ¿1ïŒPromise å°è£
AJAX ============
function getJSON(url, options = {}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(options.method || 'GET', url, true);
xhr.timeout = options.timeout || 5000;
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
try {
resolve(JSON.parse(xhr.responseText));
} catch (e) {
reject(e);
}
} else {
reject(new Error(`HTTP ${xhr.status}`));
}
}
};
xhr.onerror = () => reject(new Error('çœç»é误'));
xhr.ontimeout = () => reject(new Error('请æ±è¶
æ¶'));
xhr.send();
});
}
// ============ æš¡æ¿2ïŒsleep åœæ° ============
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// ============ æš¡æ¿3ïŒæ·±æ·èŽåœæ° ============
function deepClone(target, hash = new WeakMap()) {
if (target === null || typeof target !== 'object') return target;
if (target instanceof Date) return new Date(target);
if (target instanceof RegExp) return new RegExp(target);
if (hash.has(target)) return hash.get(target);
const clone = Array.isArray(target) ? [] : {};
hash.set(target, clone);
for (let key in target) {
if (target.hasOwnProperty(key)) {
clone[key] = deepClone(target[key], hash);
}
}
return clone;
}
ð 延䌞åŠä¹
| äž»é¢ | æšèæç« |
|---|---|
| Promise/A+ è§è | Promises/A+ 宿¹è§è |
| Event Loop | JavaScript äºä»¶åŸªç¯è¯Šè§£ |
| æå Axios | ä»é¶æå Axios |
| åŒæ¥çŒçšæŒè¿ | ä»åè°å° async/await |
ð¬ äºåšè¯é¢
äœ åšé¢è¯äžéå°è¿åªäº"æå代ç "çåïŒ
欢è¿åšè¯è®ºåºåäº«äœ çç»åïŒç¹èµæé«çé å端é¢è¯é¢åº PDF äžä»œïŒ
è§åŸæçšïŒè¯·ç¹èµ + æ¶è + å ³æ³šïŒäžæé¢åïŒãæå PromiseïŒä» 0 å®ç° Promises/A+ è§èã
æ¬æåèäºçšåæéå€ç¯é«èµæç« ïŒç»å 2025-2026 å¹Žææ°é¢è¯è¶å¿æŽçèæãåŠæéè¯¯ïŒæ¬¢è¿ææ£ïŒ