真正搞懂promise 与同步异步 新增面试话术

老大难的promise,属于道理我都懂,也会用,但就是总感觉没理解透彻
随手B站刷到一个视频 解决了我多年疑惑

B站链接

同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事
异步: 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕

模拟一

function one (){
    
    
     return 'I am one';
}
function two () {
    
    
     setTimeout(()=>{
    
    
           return 'I am two';
     },3000);
     
}
function three () {
    
    
     return 'I am three';
}

console.log(one())
console.log(two())
console.log(three())

在这里插入图片描述

  • 后台数据请求都是异步,而JS是单线程。这里用定时函数模拟请求,会发现等不到请求完成就会先执行输出,导致输出undefined

模拟二


function one (){
    
    
     return 'I am one';
}
function two () {
    
    
     return new Promise((resolve,reject)=>{
    
    
          setTimeout(()=>{
    
    
                resolve ('I am two');
          },3000);
     })
}
function three () {
    
    
     return 'I am three';
}

console.log(one())
console.log(two())
console.log(three())

在这里插入图片描述
这里因为还是单线程直接执行,没有等到promise成功态就输出了promise对象,此时的promise对象处于pending状态。

模拟三


function one (){
    
    
     return 'I am one';
}
function two () {
    
    
     return new Promise((resolve,reject)=>{
    
    
          setTimeout(()=>{
    
    
                resolve ('I am two');
          },3000);
     })
}
function three () {
    
    
     return 'I am three';
}

console.log(one())
console.log(await two())
console.log(three())

在这里插入图片描述
配合await,代码执行时await有返回结果后才会继续向下执行。
这里会先输出 I am one 然后等待三秒再输出 I am two I am three

  • 最初的解决方式是使用回调函数的方法,将后续操作一并传入,这样就可以实现拿到数据后再执行其他逻辑。
  • 但是回调过多会导致回调地狱,难以维护。promise的主要贡献就是解决了回调地狱,让请求代码更简洁。再补充async后写起来就更加舒服了。

一个值得注意的点

想起来之前面试 有一个面试官问我用promise为什么还要手写promise对象 await返回的就是promise对象,当时一下没想明白。现在回想起来…还好没去那家公司
MDN中对await的描述

如果该值不是一个 Promise,await 会把该值转换为已正常处理的Promise,然后等待其处理结果。

async function f2() {
    
    
  var y = await 20;
  console.log(y); 
}f2();
//输出20

await返回的就是promise对象,这句话其实没错,但我们结合实际开发看看
用定时器模拟异步请求,场景是需要拿到接口返回结果再进行下一步操作。

async function f2() {
    
    
  var y = await two();
  console.log(y); // 20
  console.log('下一步')
}
function two () {
    
    
     setTimeout(()=>{
    
    
           return 'I am two';
     },3000);
}
f2()
//输出 undefined
//     下一步 

这样返回的结果是undefined,异步请求若不进行手动封装,靠await自动处理,await的阻断效果是不会出现的,数据依然拿不到。
正确写法是:

async function f2() {
    
    
  var y = await two();
  console.log(y); // 20
  console.log('下一步')
}
function two () {
    
    
    return new Promise(resolve=>{
    
    
         setTimeout(()=>{
    
    
               resolve( 'I am two')
         },3000);
    })
}
f2()
//等待三秒后
//输出 I am two
//     下一步 

面试话术:

JS是单线程,但后台请求是异步执行的。开发中常常会遇到需要拿到接口数据后执行必要逻辑。
当然,这里可以使用回调函数,但代码量大了会难以维护形成回调地狱。
而使用promise函数配合async await就可以完美解决这类问题
某一步操作设置await等待返回的promise对象,promise中进行异步请求,拿到数据后在改为成功态,即可进行后续操作。
用同步的方法写异步,维护性高。

猜你喜欢

转载自blog.csdn.net/Beatingworldline/article/details/120831089