资讯专栏INFORMATION COLUMN

[面试专题]JS异步之Promise,Generator,Async

孙淑建 / 2402人阅读

摘要:所以,函数的一个重要实际意义就是用来处理异步操作,改写回调函数。表示在这里等待异步操作返回结果,再继续执行。

JS异步之Promise,Generator,Async
Promise

解决的问题:回调地狱

Promise规范:

promise有三种状态,等待(pending)、已完成(fulfilled/resolved)、已拒绝(rejected).Promise的状态只能从“等待”转到“完成”或者“拒绝”,不能逆向转换,同时“完成”和“拒绝”也不能相互转换.

promise 必须提供一个 then方法以访问其当前值、终值和据因。promise.then(resolve, reject),resolve 和 reject都是可选参数。如果 resolve 或reject 不是函数,其必须被忽略.

then 方法必须返回一个 promise 对象.

使用:

实例化promise对象需要传入函数(包含两个参数),resolve和reject,内部确定状态.resolve和reject函数可以传入参数在回调函数中使用.
resolve和reject都是函数,传入的参数在then的回调函数中接收.

var promise = new Promise(function(resolve, reject) {
    setTimeout(function(){
        resolve("好哈哈哈哈");
    });
});
promise.then(function(val){
  console.log(val)
  })

then接收两个函数,分别对应resolve和reject状态的回调,函数中接收实例化时传入的参数.

promise.then(val=>{
  //resolved
},reason=>{
  //rejected
})

catch相当于.then(null, rejection)
当then中没有传入rejection时,错误会冒泡进入catch函数中,若传入了rejection,则错误会被rejection捕获,而且不会进入catch.此外,then中的回调函数中发生的错误只会在下一级的then中被捕获,不会影响该promise的状态.

new Promise((resolve,reject)=>{
   throw new Error("错误")
 }).then(null,(err)=>{
   console.log(err,1);//此处捕获
 }).catch((err)=>{
   console.log(err,2);
 });
 // 对比
 new Promise((resolve,reject)=>{
   throw new Error("错误")
 }).then(null,null).catch((err)=>{
   console.log(err,2);//此处捕获
 });
 // 错误示例
 new Promise((resolve,reject)=>{
   resolve("正常");
 }).then((val)=>{
   throw new Error("回调函数中错误")
 },(err)=>{
   console.log(err,1);
 }).then(null,(err)=>{
   console.log(err,2);//此处捕获,也可用catch
 });

两者不等价的情况:
此时,catch捕获的并不是p1的错误,而是p2的错误,

p1().then(res=>{ 
        return p2()//p2返回一个promise对象 
     }).catch(err=> console.log(err))

一个错误捕获的错误用例:
该函数调用中即使发生了错误依然会进入then中的resolve的回调函数,因为函数p1中实例化promise对象时已经调用了catch,若发生错误会进入catch中,此时会返回一个新的promise,因此即使发生错误依然会进入p1函数的then链中的resolve回调函数.

  function p1(val){
    return new Promise((resolve,reject)=>{
      if(val){
        var len = val.length;//传入null会发生错误,进入catch捕获错误
        resolve(len);
      }else{
        reject();
      }
    }).catch((err)=>{
      console.log(err)
    })
  };
  p1(null).then((len)=>{
      console.log(len,"resolved");
  },()=>{
    console.log("rejected");
  }).catch((err)=>{
    console.log(err,"catch");
  })

Promise回调链:

promise能够在回调函数里面使用 return 和 throw, 所以在then中可以return出一个promise对象或其他值,也可以throw出一个错误对象,但如果没有return,将默认返回 undefined,那么后面的then中的回调参数接收到的将是undefined.

  function p1(val){
    return new Promise((resolve,reject)=>{
      val==1?resolve(1):reject()
    })
  };
  function p2(val){
    return new Promise((resolve,reject)=>{
      val==2?resolve(2):reject();
    })
  };
  let promimse = new Promise(function(resolve,reject){
           resolve(1)
  })
    .then(function(data1) {
         return p1(data1)//如果去掉return,则返回undefined而不是p1的返回值,会导致报错
    })
    .then(function(data2){
        return p2(data2+1)
    })
    .then(res=>console.log(res))
Generator函数:

generator函数使用:
1、分段执行,可以暂停

2、可以控制阶段和每个阶段的返回值
3、可以知道是否执行到结尾

function* g() {
    var o = 1;
    yield o++;
    yield o++;
}
var gen = g();

console.log(gen.next()); //  Object {value: 1, done: false}

var xxx = g();

console.log(gen.next()); // Object {value: 2, done: false}
console.log(xxx.next()); // Object {value: 1, done: false}
console.log(gen.next()); // Object {value: undefined, done: true}

generator和异步控制:
利用Generator函数的暂停执行的效果,可以把异步操作写在yield语句里面,等到调用next方法时再往后执行。这实际上等同于不需要写回调函数了,因为异步操作的后续操作可以放在yield语句下面,反正要等到调用next方法时再执行。所以,Generator函数的一个重要实际意义就是用来处理异步操作,改写回调函数。

async和异步:

用法:

async 表示这是一个async函数,await只能用在这个函数里面。

await 表示在这里等待异步操作返回结果,再继续执行。

await 后一般是一个promise对象

示例:async用于定义一个异步函数,该函数返回一个Promise。
如果async函数返回的是一个同步的值,这个值将被包装成一个理解resolve的Promise,等同于return Promise.resolve(value)。

await用于一个异步操作之前,表示要“等待”这个异步操作的返回值。await也可以用于一个同步的值。

let timer = async function timer(){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve("500");
        },500);
    });
}
timer().then(result => {
  console.log(result);  //500
}).catch(err => {
    console.log(err.message);
});
//返回一个同步的值
let sayHi = async function sayHi(){
  let hi = await "hello world";   
  return hi;  //等同于return Promise.resolve(hi);
}
sayHi().then(result => {
  console.log(result);
});

参考:
Promise迷你书
promise笔记
手写promise
promise实现

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/51201.html

相关文章

  • [面试专题]JS异步Promise,Generator,Async

    摘要:所以,函数的一个重要实际意义就是用来处理异步操作,改写回调函数。表示在这里等待异步操作返回结果,再继续执行。 JS异步之Promise,Generator,Async Promise 解决的问题:回调地狱 Promise规范: promise有三种状态,等待(pending)、已完成(fulfilled/resolved)、已拒绝(rejected).Promise的状态只能从...

    klivitamJ 评论0 收藏0
  • [面试专题]JS异步Promise,Generator,Async

    摘要:所以,函数的一个重要实际意义就是用来处理异步操作,改写回调函数。表示在这里等待异步操作返回结果,再继续执行。 JS异步之Promise,Generator,Async Promise 解决的问题:回调地狱 Promise规范: promise有三种状态,等待(pending)、已完成(fulfilled/resolved)、已拒绝(rejected).Promise的状态只能从...

    xioqua 评论0 收藏0
  • 面试篇】寒冬求职季你必须要懂的原生JS(中)

    摘要:如果你还没读过上篇上篇和中篇并无依赖关系,您可以读过本文之后再阅读上篇,可戳面试篇寒冬求职季之你必须要懂的原生上小姐姐花了近百个小时才完成这篇文章,篇幅较长,希望大家阅读时多花点耐心,力求真正的掌握相关知识点。 互联网寒冬之际,各大公司都缩减了HC,甚至是采取了裁员措施,在这样的大环境之下,想要获得一份更好的工作,必然需要付出更多的努力。 一年前,也许你搞清楚闭包,this,原型链,就能获得...

    andycall 评论0 收藏0
  • 前端面试题 -- JavaScript(二)

    摘要:抛出的错误对象会被方法回调函数接收到命令命令后面是一个对象,返回该对象的结果。有人将其称之为宏任务微任务,定时器就属于宏任务的范畴。 前言 上一篇 前端面试题-JavaScript(一), 感兴趣的小伙伴也可以移步这里查看 完整版JavaScript面试题,面试题会不定期更新加进去一些个人工作中遇到的或者认为比较重要的东西,后面会涉及到前端的各个方面,感兴趣的小伙伴可以关注哦! 如果文...

    cgspine 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<