前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >javascript异步与promise

javascript异步与promise

作者头像
陌上寒
发布2019-04-02 15:08:48
8800
发布2019-04-02 15:08:48
举报
文章被收录于专栏:前端进阶前端进阶

我们说处理javascript异步最常用的方式就是通过回调函数,对于回调函数我们昨天对此做了介绍 简单快速, 我们一般使用嵌套回调或者链式回调,会产生以下问题

  1. 当采用嵌套回调时,会导致层级太多,不利于维护
  2. 所以我们又采用了链式回调,对嵌套回调进行拆分,拆分后的函数间耦合度很高,
  3. 如果需要传递参数,函数之间的关联性会更高,而且要对参数进行校验以提高代码的健壮性
  4. 如果将我们自己的回调函数传递给第三方插件或者库,就要考虑一些不可控因素
    • 调用回调过早
    • 调用回调过晚(或不被调用)
    • 调用回调次数过多或者过少

promise的存在就是为了解决以上问题 虽然我们日常写回调函数不会有这么严格的要求,但是如果不这样去写回调函数,就会存在隐患,当在团队协作的时候,显得编码规范显得尤为重要

本文不重点介绍如何使用promise,重点介绍的是promise解决了哪些异步回调出现的问题。

什么是promise

我们来看一个场景,有助于我们了解promise

设想一下这个场景,我去KFC,交给收银员10元,下单买一个汉堡,下单付款。到这里,我已经发出了一个请求(买汉堡),启动了一次交易。 但是做汉堡需要时间,我不能马上得到这个汉堡,收银员给我一个收据来代替汉堡。到这里,收据就是一个承诺(promise),保证我最后能得到汉堡。 所以我需要好好的保留的这个收据,对我来说,收据就是汉堡,虽然这张收据不能吃,我需要等待汉堡做好,等待收银员叫号通知我 等待的过程中,我可以做些别的事情 收银员终于叫到了我的号,我用收据换来了汉堡 当然还有一种情况,当我去柜台取汉堡的时候,收银员告诉我汉堡卖光了,做汉堡的师傅受伤了等等原因,导致了我无法得到这个汉堡 虽然我有收据(承诺),但是可能得到汉堡(成功),可能得不到汉堡(失败) 我由等待汉堡变成了等到或者等不到,这个过程不可逆,

上面很形象的介绍了promise,上面的等待汉堡和得到汉堡,汉堡卖光了,得不到汉堡,分别对应promise的三种状态 三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)(一旦状态改变,就不会再变)

回调函数调用过早

调用过早就是将异步函数作为同步处理了, 我们之前说过,javascript以单线程同步的方式执行主线程,遇到异步会将异步函数放入到任务队列中, 当主线程执行完毕,会循环执行任务队列中的函数,也就是事件循环,直到任务队列为空。

事件循环和任务队列

事件循环就像是一个游乐场,玩过一个游戏后,你需要重新排到队尾才能再玩一次 任务队列就是,在你玩过一个游戏后,可以插队接着玩

我们看一个栗子

代码语言:javascript
复制
    const promise = new Promise((resolve, reject) => {
      resolve("成功啦")
    });
    promise.then(res => {
      console.log(res);
      console.log("我是异步执行的");
    })
    console.log('我在主线程');

看下输出,重点看输出顺序

代码语言:javascript
复制
//我在主线程
//成功啦
//我是异步执行的

直接手动是promise的状态切为成功状态,console.log("我是异步执行的");这段代码也是异步执行的 提供给then()的回调永远都是异步执行的,所以promise中不会出现回调函数过早执行的情况

回调函数调用过晚或不被调用

回调函数调用过晚

回调函数调用过晚的处理原理和调用过早很类似, 在promise的then()中存放着异步函数,所有的异步都存在于js的任务队列中,当js的主线程执行完毕后,会依次执行任务队列中的内容,不会出现执行过晚的情况

回调函数不被调用

我们用栗子说话

代码语言:javascript
复制
    const promise = new Promise((resolve, reject) => resolve('成功啦'))
    promise.then(s => console.log(s));
    console.log('我在主线程');

成功状态的输出

代码语言:javascript
复制
//我在主线程
//成功啦

成功状态下回调被调用 继续看一下失败的回调

代码语言:javascript
复制
    const promise = new Promise((resolve, reject) => reject('失败啦'))
   promise.then(null, s => console.log(s));
   console.log('我在主线程');

失败状态的输出

代码语言:javascript
复制
//我在主线程
//失败啦

失败状态下回调被调用 所以说,不管是失败还是成功,回调函数都会被调用

回调函数调用次数过多或者过少

调用次数过多

我们之前说了promise有三种状态 pending(进行中)、fulfilled(已成功)和rejected(已失败)状态一旦状态改变,就不会再变 一个栗子

代码语言:javascript
复制
    const promise = new Promise((resolve, reject) => {
      reject('失败啦')
      resolve('成功啦')
    });
    promise.then(res => {
      console.log(`我是异步执行的成功:${res}`);
    },err=>{
      console.log(`我是异步执行的失败:${err}`);
    }).catch(err => {
      console.log(err);
    })
    console.log('我在主线程');

输出

代码语言:javascript
复制
//我在主线程
//我是异步执行的失败:失败啦

当状态变为失败时,就不会再变为成功,成功的函数也不会执行,反之亦然

调用次数过少

回调函数正常是调用一次,过少=>0次=>回调函数不被调用,上面刚刚讨论过

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是promise
  • 回调函数调用过早
    • 事件循环和任务队列
    • 回调函数调用过晚或不被调用
      • 回调函数调用过晚
        • 回调函数不被调用
        • 回调函数调用次数过多或者过少
          • 调用次数过多
            • 调用次数过少
            相关产品与服务
            Prowork 团队协同
            ProWork 团队协同(以下简称 ProWork )是便捷高效的协同平台,为团队中的不同角色提供支持。团队成员可以通过日历、清单来规划每⽇的工作,同时管理者也可以通过统计报表随时掌握团队状况。ProWork 摒弃了僵化的流程,通过灵活轻量的任务管理体系,满足不同团队的实际情况,目前 ProWork 所有功能均可免费使用。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档