重温promise与async/await

本文深入探讨了Promise异步编程的概念,包括其三种状态、不变性及常用方法。接着介绍了async/await作为升级版的异步解决方案,通过实例展示了其工作原理。同时,文章还涉及了JavaScript的宏任务与微任务执行机制,帮助读者理解异步执行顺序。最后,提供了相关资源链接以便进一步学习。

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

1. promise异步编程

promise对象代表一个异步操作,有三种状态:pending(进行中),fulfilled(resolved)(已成功),rejected(已失败)。
特点

  • 对象的状态不受外界影响
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果

注: promise状态改变只有两种可能:pending —> fulfilled, pending —> rejected

实例方法

  • Promise.prototype.then() :为promise实例添加状态改变时的回调函数,第一个参数为resolved状态回调函数,第二个(可选)为rejected状态的回调函数,返回一个新的promise实例。
  • Promise.prototype.catch():用于指定发生错误时的回调函数,参数为rejected状态回调函数,返回一个新promise对象。
  • Promise.prototype.finally():用于指定不管promise对象最后状态如何,都会执行的操作,其回调函数不接受任何参数。

promise基本实例

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

promise方法

  1. Promise.all()const p = Promise.all([p1, p2, p3]);
  • 只有p1,p2,p3的状态都变成fulfilled, p的状态才会变成fulfilled,此时p1,p2,p3的返回值组成一个数组,传递给p的回调函数。
  • 只要p1,p2,p3之中有一个被rejectedp的状态就会变成rejected,此时第一个被rejected的实例的返回值,会传递给p的回调函数。
  1. promise.race()const p = Promise.race([p1, p2, p3]);
  • 只要p1,p2,p3之中有一个实例率先改变状态,p的状态就会跟着改变,且那个率先改变的promise实例的返回值,就传递给p的回调函数。
  1. Promise.resolve()/Promise.reject():将现有对象转为一个promise对象。

实现一个完美符合Promise/A+规范的Promise:

function myPromise(
	constructor){    
		let self = this;
        self.status = "pending"; //定义状态改变前的初始状态
    	self.value = undefined; //定义状态为resolved的时候的状态
    	self.reason = undefined; //定义状态为rejected的时候的状态
    
	function resolve(value){
    	//两个==="pending",保证了状态的改变是不可逆的
       if(self.status === "pending"){
          self.value = value;
          self.status = "resolved";
       }
    }
    
	function reject(reason){
        //两个==="pending",保证了状态的改变是不可逆的
       if(self.status === "pending"){
          self.reason = reason;
          self.status = "rejected";
      }
    }
    
	//捕获构造异常
    try{
       constructor(resolve, reject);
    }catch(e){
       reject(e);
    }
}

//在myPromise的原型上定义链式调用的then方法
myPromise.prototype.then = function(onFullfilled, onRejected){
	let self = this;   
	switch(self.status){     
		case "resolved":
        	onFullfilled(self.value);
        	break;
      	case "rejected":
        	onRejected(self.reason);
        	break;     
		default:  
	}
}

2. 升级版异步编程解决方案async/await:

基本实例

async function getStockPriceByName(name) {
  const symbol = await getStockSymbol(name);
  const stockPrice = await getStockPrice(symbol);
  return stockPrice;
}

getStockPriceByName('goog').then(function (result) {
  console.log(result);
});

关键知识点

  • async函数返回的是一个promise对象,内部return语句返回的值会成为then方法回调函数的参数。
  • await是从右向左执行,遇到await就让出线程,阻塞后面的代码。
  • await后如果是一个promise,会等待状态为fulfilled再返回resolved的值,如果不是,就直接返回对应的值。
  • async函数只有内部的异步操作都执行完,才会执行then方法指定的回调函数。
  • 如果await后面的异步操作出错,那么等同于async函数返回的promise对象被reject

3. 宏任务与微任务

JS引擎的执行机制

  • 开始执行当前调用栈中的宏任务,过程中如果遇到宏任务,就把它推入【宏任务队列】中,如果遇到微任务,就将其推入【微任务队列】中;
  • 在当前宏任务的同步代码执行完毕后,再依次执行队列中所有的微任务;
  • 在当前微任务全部执行完毕后,检查渲染,GUI线程接管渲染;
  • 渲染完毕后,js线程接管,开始执行队列中的下一个宏任务;

执行流程图如下
在这里插入图片描述
宏任务与微任务定义

  • macro-task(宏任务):当前调用栈中执行的代码,如主代码块scriptsetTimeoutsetInterval等定时器。
  • micro-task(微任务):当前宏任务执行完,在下一个宏任务开始之前需要执行的任务,如promise.thenprocess.nextTick等。

测试一下以上知识理解
请问以下代码输出结果是什么?

	async function async1() {
        console.log( 'async1 start' )
        await async2()
        console.log( 'async1 end' )
    }
    
    async function async2() {
        console.log( 'async2' )
    }
    
    console.log( 'script start' )
    
    setTimeout( function () {
        console.log( 'setTimeout' )
    }, 0 )
    
    async1();
    
    new Promise( function ( resolve ) {
        console.log( 'promise1' )
        resolve();
    } ).then( function () {
        console.log( 'promise2' )
    } )
    
    console.log( 'script end' )

正确结果是:

 	script start
    async1 start
    async2
    promise1
    script end
    promise2
    async1 end
    setTimeout

你猜对了吗??


参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值