JavaScript通過外賣訂單講解異步編程
同步vs異步-點外賣的智慧
想象一下你要準備一頓晚餐:
同步方式(不推薦):
- 走進廚房開始煮飯
- 站在灶臺前盯著鍋,什么都不做,直到飯煮好(20分鐘)
- 飯好了才開始洗菜切菜
- 再花30分鐘炒菜
- 總共耗時:50分鐘
異步方式(聰明做法):
- 開始煮飯(設置定時器)
- 在飯煮的同時洗菜切菜
- 飯好了的提示音響起時處理飯
- 繼續(xù)炒菜
- 總共耗時:35分鐘
JavaScript的異步編程就像是那個聰明的廚師,讓多個任務可以同時進行!
回調(diào)函數(shù)-JavaScript的電話通知
最早的異步處理方式是回調(diào)函數(shù):
// 點外賣的比喻:下單后留下電話號碼,外賣到了打電話通知你
orderFood('pizza', function(pizza) {
console.log(`我的${pizza}到了!可以開動了!`);
});
console.log('在等外賣的時候,我可以繼續(xù)刷劇...');但問題來了——如果你需要按順序做多件事呢?
// “回調(diào)地獄”出現(xiàn)了!
orderFood('pizza', function(pizza) {
getDrink('cola', function(cola) {
buyNapkins(function(napkins) {
console.log(`準備好享用${pizza}+${cola}了,還有${napkins}張餐巾紙`);
// 更多嵌套...
});
});
});這就像是:等外賣→外賣到了買飲料→飲料到了買紙巾……效率太低了!
Promise-外賣訂單追蹤系統(tǒng)
ES6帶來了Promise,就像外賣平臺的應用,可以追蹤訂單狀態(tài):
// 創(chuàng)建一個Promise就像下一個外賣訂單
const foodOrder = new Promise((resolve, reject) => {
// 模擬烹飪時間
setTimeout(() => {
const success = Math.random() > 0.1; // 90%的成功率
success ? resolve('香噴噴的披薩') : reject('抱歉,烤箱壞了');
}, 2000);
});
// 追蹤訂單狀態(tài)
foodOrder
.then(food => {
console.log(`?? ${food}送達!`);
return '吃完了,該收拾了'; // 可以繼續(xù)返回新的Promise
})
.then(message => {
console.log(message);
})
.catch(error => {
console.log(`?? ${error}`);
})
.finally(() => {
console.log('這次訂餐體驗結束了');
});
console.log('訂單已下,我可以繼續(xù)工作...');async/await-像寫同步代碼一樣寫異步
ES7的async/await讓異步代碼看起來像同步代碼一樣直觀:
async function enjoyDinner() {
try {
console.log('開始準備晚餐...');
// 看起來是同步的,但實際上是異步的!
const pizza = await orderPizza();
console.log(`${pizza}準備好了`);
const drink = await orderDrink();
console.log(`${drink}也到了`);
// 這兩個可以同時進行!
const [napkins, movie] = await Promise.all([
buyNapkins(),
loadMovie()
]);
console.log(`完美!有${pizza}、${drink}、${napkins}和電影${movie}`);
} catch (error) {
console.log(`晚餐計劃失敗:${error}`);
}
}
// 模擬的異步函數(shù)
function orderPizza() {
return new Promise(resolve => {
setTimeout(() => resolve('??意大利香腸披薩'), 2000);
});
}事件循環(huán)-JavaScript的時間管理大師
JavaScript是單線程的,但它有一個神奇的事件循環(huán)機制:
console.log('1. 開始做飯');
setTimeout(() => {
console.log('4. 定時器到時間了(飯煮好了)');
}, 0);
Promise.resolve()
.then(() => {
console.log('3. Promise微任務(嘗一下味道)');
});
console.log('2. 繼續(xù)切菜');
// 輸出順序:
// 1. 開始做飯
// 2. 繼續(xù)切菜
// 3. Promise微任務(嘗一下味道)
// 4. 定時器到時間了(飯煮好了)簡單來說:
- 同步任務立即執(zhí)行
- 微任務(Promise)在當前任務結束后立即執(zhí)行
- 宏任務(setTimeout)在微任務之后執(zhí)行
實際應用-有趣的例子
// 模擬一個加載進度指示器
async function loadContentWithProgress() {
const tasks = [
'加載用戶數(shù)據(jù)',
'獲取朋友圈',
'下載圖片',
'初始化聊天'
];
for (let i = 0; i < tasks.length; i++) {
// 模擬每個任務的耗時
await new Promise(resolve =>
setTimeout(resolve, Math.random() * 1000 + 500)
);
const progress = ((i + 1) / tasks.length) * 100;
console.log(`?? ${tasks[i]}... 進度:${progress.toFixed(0)}%`);
}
console.log('? 所有內(nèi)容加載完成!');
}
// 使用Promise.race實現(xiàn)超時控制
function fetchWithTimeout(url, timeout = 3000) {
const fetchPromise = fetch(url);
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('請求超時')), timeout);
});
return Promise.race([fetchPromise, timeoutPromise]);
}異步編程的黃金法則
- 避免阻塞:長時間運行的任務要異步化
- 錯誤處理:不要忘記.catch()或try-catch
- 適度使用:不是所有東西都需要異步
- 保持簡單:能用async/await就不用復雜的Promise鏈
總結
JavaScript的異步編程就像生活中的多任務處理:我們不會等水燒開時傻站著,而是同時準備其他食材。從回調(diào)函數(shù)到Promise再到async/await,JavaScript為我們提供了越來越優(yōu)雅的方式來處理異步操作。
記住,好的異步代碼就像一場精心編排的交響樂——每個部分在正確的時間奏響,整體和諧而不混亂。
希望這篇文章讓你對JavaScript異步編程有了更直觀的理解!現(xiàn)在,試著把你的下一個耗時操作改成異步吧,讓你的應用變得更加流暢!
小挑戰(zhàn):你能用async/await寫一個模擬“同時煮面、煎蛋、烤面包”的早餐制作程序嗎?
以上就是JavaScript通過外賣訂單講解異步編程的詳細內(nèi)容,更多關于JavaScript異步編程的資料請關注腳本之家其它相關文章!
相關文章
詳解JavaScript中new操作符的解析和實現(xiàn)
這篇文章主要介紹了JavaScript中new操作符的解析和實現(xiàn),幫助大家更好的理解和學習JavaScript,感興趣的朋友可以了解下2020-09-09
JS遍歷JSON數(shù)組及獲取JSON數(shù)組長度操作示例【測試可用】
這篇文章主要介紹了JS遍歷JSON數(shù)組及獲取JSON數(shù)組長度操作,涉及javascript簡單json數(shù)組遍歷與運算相關操作技巧,需要的朋友可以參考下2018-12-12
利用純js + transition動畫實現(xiàn)移動端web輪播圖詳解
這篇文章主要給大家介紹了利用純js + transition動畫實現(xiàn)移動端web輪播圖的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考借鑒,下面來一起看看吧。2017-09-09
Javascript 一些需要注意的細節(jié)(必看篇)
下面小編就為大家?guī)硪黄狫avascript 一些需要注意的細節(jié)(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07

