异步基础:从 setTimeout 到 Promise

本文深入讲解JavaScript中的异步处理方式,包括setTimeout函数的基本用法、Promise对象的优势及使用场景、链式Promise的实现原理,以及async和await如何简化异步编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、setTimeout 函数

  • 定义:setTimeout() 函数在指定一个毫秒数后,会去执行给定的函数。
    • 1000ms(毫秒) = 1s(秒)
    • 给定的函数只会执行一次,如果需要重复执行,可以使用 setInterval() 函数
    • 使用 clearTimeout() 方法可以阻止给定的函数被运行
  • 语法:
setTimeout(function, milliseconds, param1, param2, ...)
  • function:必须,给定的函数
  • milliseconds:可选,毫秒数
  • paramX:可选,给定的函数的实际参数

二、Promise 概述

1. 定义

  • Promise 是一个内置对象,代表一个异步操作的最终结果(完成/失败)。他的最重要的作用就是将异步操作转换为同步操作

Old-fashioned passed-in callback:

function successCallback(result) {
    console.log('Audio file ready at URL: ' + result)
}

function failureCallback(error) {
    console.log('Error generating audio file : ' + error)
}

createAudioFileAsync(audioSettings, successCallback, failureCallback)

Using promise:

createAudioFileAsync(audioSettings)
    .then(successCallback)
    .catch(failureCallback)
  • 三种状态

    • pending:初始化状态
    • filfulled:异步操作成功
    • rejected :异步操作失败
  • 其他描述

    • settled:表示 filfulled 状态或者 rejected 状态
    • resolved:表示一个 promisesettled 或者 locked-in 以便去匹配另外一个 promise 的状态

    2. 优点

1. 安全
  1. then() 方法中添加的回调函数在 JavaScript 的 event loop 的 completion of the current run 之前不会被调用
  2. 即使在 promise 中的异步操作已经成功或者失败了之后才添加回调函数,这些回调还是会被调用
  3. 多个回调函数可以通过调用多次 then() 方法。这些回调函数依据他们插入的顺序,一个接一个的调用。
2. 可链式,避免层层嵌套

层层嵌套,会形成一个 Callback Pyramid of Doom,即「死亡回调金字塔」

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

使用Promise

doSomething()
.then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);

关于链式 promise,详见下节

3. 缺点

  1. Promise 对象一旦创建立即执行,无法中止
  2. 对于 pending 状态,无法确定是刚刚开始还是即将结束
  3. Promise 对象内部抛出的异常,必须得通过回调函数捕获,否则会被忽略

三、链式Promise

链式 Promise 主要通过 then() 方法返回一个新的 Promise 对象来实现。
then()catch()finally() 这三个方法被用于当 promisesettled 之后的进一步行为。

  • then() 方法
    • 两个参数,一个是 fulfilled 后的成功 resolve 回调函数,另外一个是 rejected 后的失败 reject 回调函数。
    • 返回值是一个 promise
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('foo');
  }, 300);
});

myPromise
  .then(handleResolvedA, handleRejectedA)
  .then(handleResolvedB, handleRejectedB)
  .then(handleResolvedC, handleRejectedC);

then() 方法中可以简单地忽略处理失败 reject 的回调函数,将其交给 catch() 方法去处理,catch() 方法可以看作是个没有成功 fulfilled 回调函数的 then() 方法。

Importantthen() 中的回调函数尽量返回结果,这样才能让 catch() 方法去捕获上一个 Promise 传递下来的异常。

四、asyncawait

用关键字 async 来声明一个异步函数,关键字 await 可以在异步函数中搭配使用。异步函数最重要的作用就是去避免显式配置链式 promise,使得代码更加的简洁。

function resolveAfter2seconds(){
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolve')
    }, 2000)
  })
}

async function asyncCall( ){
  console.log('calling...')
  let result = await resolveAfter2seconds()
  console.log(result)
}

asyncCall()

/**Output:
"calling..."
"resolve"
*/

参考

  1. Promise
  2. Using Promise
  3. Promised对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值