JavaScript异步编程发展史(Promise Demo)

异步编程

     众所周知,Javascript语言的执行环境是"单线程"(single thread)。
     所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,才会执行下一个任务。所以,在程序执行的每一步,都可以推断出程序的状态,这是因为后面的指令总是在前面的指令完成后才会执行,即同步行为。
     相对的,异步行为是必要的,因为强制进程等待一个长时间的操作通常是不可行的(同步操作则必须等),比如向远程服务器发送请求并等待响应,就会出现长时间的等待。当然,异步代码不容易推断,设计一个可以推断异步代码实况状态的系统是很难的,JavaScript在实现这样一个系统的过程中也经历的几次迭代。

以往的异步编程模式

     在早期的Javascript中,只支持定义回调函数来表明异步操作完成。

function double(value){
   
  setTimeOut(()=>{
   
    setTimeOut(console.log,0,value)
 },1000);
}

     这段代码没有什么神秘的,之所以说他是一个异步函数,是因为,1000ms之后,JavaScript会把会把回调函数推到自己的队列上等待执行。推到队列之后,回调什么时候出列被执行就是未知的了。另外,double函数在setTimeOut成功调度异步操作之后会立即退出。

异步返回值

     假设setTimeOut操作会返回一个有用的值,可以给异步操作提供一个回调,这个回调中包含要使用异步返回值的代码(作为回调的参数)。

function double(value,callback){
   
   setTimeOut(()=>callback(value),1000);
}

     这里的setTimeOut调用告诉JavaScript运行时在1000ms之后把一个函数推到消息队列里。如果异步返值又依赖另一个异步返回值,就会出现嵌套(会回调地狱),非常难以维护。

Promise

     ECMAScript 6 新增的引用类型Promise其实是一个构造函数,可以通过new操作符来实例化。他自己身上有allrejectresolve等方法,原型上有thencatch等方法。
     大致介绍了promise出现的背景,接下来就回到写这篇文章的初衷🥧~
     用一些小demo来学习promise~

Promise基础题

题目一

  const promise1 = new Promise((resolve, reject) => {
   
       console.log('promise1')
     })
   console.log('1', promise1);
  • 首先遇到new Promise,执行该构造函数中的同步代码console.log(‘promise1’ )
  • 接下来,执行同步代码,打印1,此时Promise1的状态为pending待定中;

结果:

'promise1'
'1' Promise{
   <pending>}

题目二

const promise = new Promise((resolve, reject) => {
   
     console.log(1);
     resolve('success')
     console.log(2);
});
promise.then(() => {
   
     console.log(3);
});
   console.log(4);
  • 首先遇到new Promise,执行同步代码打印1;
  • 遇到resolve('success'),将promise的状态改为resolve,并将值(success)保存下来;
  • 执行同步代码打印出2;
  • 继续向下,promise.then是微任务,所以将promise.then加入微任务队列,此时promise状态已经改变为resolved
  • 执行同步代码打印4;
  • 至此,同步任务执行完毕。本轮事件循环(整段script代码)的宏任务执行完毕,开始执行微任务队列的promise.then
    结果:1 2 4 3

题目三

const promise = new Promise((resolve, reject) => {
   
    console.log(1);
    console.log(2);
});
promise.then(() => {
   
   console.log(3);
});
 console.log(4);
  • 和第二题类似,但是promise没有状态,所以promise.then( )不会执行。所以,执行promise.then前提的该promise的状态已经变为成功或拒绝
    结果:1 2 4

题目四

const promise1 = new Promise((resolve, reject) => {
   
    console.log('promise1')
    resolve('resolve1')
})
const promise2 = promise1.then(res => {
   
   console.log(res)
})
console.log('1', promise1);
console.log('2', promise2);
  • 首先遇到new Promise,执行同步代码打印promise1
  • 遇到resolve,将promise1的状态修改为resolved,并将值保存下来;
  • promise.then( )放入微任务队列;
  • 执行同步代码,promise1的状态为resolve,promise2的状态为pending
  • 本轮宏任务执行完毕,开始执行微任务队列,此时状态为resolve

结果:

'promise1'
'1' Promise{
   <resolved>: 'resolve1'}
'2' Promise{
   <pending>}
'resolve1'

题目五

const fn = () => (new Promise((resolve, reject) => {
   
   console.log(1);
   resolve('success')
}))
fn().then(res => {
   
   console.log(res)
})
console.log('start')
  • 首先执行同步代码打印1;
  • 将promise状态改为resolve,并保存值;
  • fn().then放入微任务队列;
  • 执行同步代码start;
  • 执行微任务,res为上一层的promise对象,值为success。

结果:

1
'start'
'success'

promise结合setTimeout

题目一

console.log('start')
  setTimeout(() => {
   
     console.log('time')
  })
Promise.resolve().then(() => {
   
    console.log('resolve')
})
console.log('end')
  • 整段js代码作为一个宏任务,同步代码直接压入执行栈;
  • setTimeout放入宏任务队列
  • promise.then()放入微任务队列;
  • 执行同步代码打印end;
  • 本轮宏任务执行完毕。开始执行微任务队列中的promise.then
  • 开启下一轮事件循环,执行宏任务setTimeOut。

结果:

'start'
'end'
'resolve'
'time'

题目二

const promise = new Promise((resolve, reject) => {
   
  console.log(1);
  setTimeout(() => {
   
      console.log("timerStart");
      resolve("success");
      console.log("timerEnd");
   }, 0);
   console.log(2);
});
promise.then((res) => {
   
     console.log(res);
});
console.log(4);
  • 首先遇到new Promise,执行同步代码打印1;
  • setTimeOut放入宏任务队列中; 执行同步代码打印2;
  • promise.then放入微任务队列;执行同步代码打印4;
  • 进入第二轮循环,执行宏任务setTimeOut,输出timerstart,timerEnd,将promise状态变为resolve,并保存值;
  • 此时,promise状态为resolve,执行console.log同步代码,res为上一层返回的promise对象。

结果:

1
2
4
"timerStart"
"timerEnd"
"success"

题目三

Promise.resolve().then(() => {
   
    console.log('promise1');
    const timer2 = setTimeout(() => {
   
      console.log('timer2')
  }, 0)
});
const timer1 = setTimeout(() => {
   
    console.log('timer1')
   Promise.resolve().then(() => {
   
      console.log('promise2')
  })
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值