喔唷网 - 网络从业者技术信息综合门户!

当前位置: 主页 > 教程技术 > 编程语言 > javascript

JavaScript异步编程 让代码学会"多线程"思考

时间 : 2025-04-23 12:01来源 : 喔唷网作者 : 喔唷教程点击 :
欢迎来到JavaScript最烧脑也最有趣的部分!异步编程就像教你的代码"一心多用",让它能在等待时不做"木头人"。准备好迎接挑战了吗?我们将从回调地狱一路升级到async/await的优雅世界! 9.1 同步与异步

欢迎来到JavaScript最烧脑也最有趣的部分!异步编程就像教你的代码"一心多用",让它能在等待时不做"木头人"。准备好迎接挑战了吗?我们将从回调地狱一路升级到async/await的优雅世界!

9.1 同步与异步概念 - 快餐店的点餐对比

同步代码就像排队点餐

console.log("1. 排队点餐");
console.log("2. 付款并等待取餐");
console.log("3. 拿到汉堡");
console.log("4. 开始吃");
// 严格按照顺序执行,前一步没完成后面就得等着

异步代码像取号点餐

console.log("1. 取号点餐");
setTimeout(() => {
  console.log("3. 取餐铃响,去拿汉堡");
}, 1000);
console.log("2. 先找座位玩手机");
// 输出顺序:1 → 2 → 3

关键区别

  • 同步:阻塞式,一步接一步
  • 异步:非阻塞,可以同时处理多个任务

9.2 回调函数模式 - 最早的"电话通知"

回调函数是最基础的异步处理方式:

function orderBurger(callback) {
  console.log("下单汉堡...");
  setTimeout(() => {
    console.log("汉堡做好了!");
    callback("汉堡");
  }, 2000);
}

orderBurger((burger) => {
  console.log(`吃${burger}`);
});

回调地狱的现实例子

// 模拟点餐流程:选餐 → 付款 → 取餐 → 吃
chooseFood((food) => {
  makePayment(food, (receipt) => {
    pickUpFood(receipt, (meal) => {
      eat(meal);
    });
  });
});
// 这种金字塔式代码难以阅读和维护

9.3 Promise对象 - 异步的"承诺书"

Promise解决了回调地狱问题,让异步代码更清晰:

function orderPizza() {
  return new Promise((resolve, reject) => {
    console.log("开始做披萨...");
    setTimeout(() => {
      if (Math.random() > 0.2) {
        resolve("pisha"); // 成功时调用
      } else {
        reject("烤箱坏了!"); // 失败时调用
      }
    }, 1500);
  });
}

orderPizza()
  .then(pizza => console.log(`吃${pizza}`))
  .catch(err => console.error(`失败:${err}`));

Promise链式调用

// 模拟:登录 → 获取用户信息 → 加载好友列表
login(user)
  .then(token => getUserInfo(token))
  .then(user => loadFriends(user.id))
  .then(friends => console.log(friends))
  .catch(err => console.log(err));

9.4 async/await语法 - 异步的"同步写法"

async/await是Promise的语法糖,让异步代码看起来像同步代码:

async function dinnerTime() {
  try {
    console.log("1. 下单晚餐");
    const burger = await orderBurger(); // 等待汉堡完成
    const fries = await orderFries();   // 等待薯条完成
    console.log(`3. 开始吃${burger}+${fries}`);
  } catch (err) {
    console.log("点餐失败:", err);
  }
}

dinnerTime();
console.log("2. 等待时刷手机");
// 输出顺序:1 → 2 → 3

并行优化

async function fastDinner() {
  const [burger, fries] = await Promise.all([
    orderBurger(),
    orderFries()
  ]);
  console.log(`快餐完成:${burger}+${fries}`);
}
// 同时下单汉堡和薯条,等两者都完成

9.5 事件循环机制 - JavaScript的"时间管理术"

理解事件循环是掌握异步编程的核心:

console.log("开始");

setTimeout(() => console.log("定时器"), 0);

Promise.resolve().then(() => console.log("Promise"));

console.log("结束");

/* 输出顺序:
   开始
   结束
   Promise
   定时器
*/

事件循环原理

  1. 调用栈:执行同步代码
  2. 任务队列:微任务队列:Promise回调、MutationObserver等宏任务队列:setTimeout、setInterval、I/O等
  3. 事件循环不断检查:调用栈空 → 执行所有微任务 → 执行一个宏任务 → 重复

本章总结

  1. 同步代码顺序执行,异步代码非阻塞
  2. 回调函数是最基础的异步处理方式
  3. Promise提供了更优雅的链式调用
  4. async/await让异步代码像同步代码一样易读
  5. 事件循环机制是JavaScript异步的核心

实战练习

  1. 用Promise实现一个随机成功/失败的抽奖函数
  2. 使用async/await改写以下回调代码:
fetchData(data => {
  processData(data, result => {
    displayResult(result);
  });
});
  1. 预测以下代码的输出顺序并解释:
console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);

生活剧场

// 模拟早餐制作流程
async function makeBreakfast() {
  try {
    // 并行启动咖啡机和烤面包机
    const [coffee, toast] = await Promise.all([
      startCoffeeMachine(),
      makeToast()
    ]);
    
    // 然后煎鸡蛋
    const eggs = await fryEggs();
    
    console.log(`早餐完成:${coffee}+${toast}+${eggs}`);
    return true;
  } catch (err) {
    console.log("早餐失败:", err);
    return false;
  }
}

// 使用
makeBreakfast().then(success => {
  if (success) {
    console.log("美好的一天开始了!");
  }
});

下一章我们将进入DOM操作的世界,学习如何让网页"动"起来!准备好成为网页魔术师了吗?

栏目列表

关联类容

热点推荐

栏目推荐

猜你喜欢