资讯专栏INFORMATION COLUMN

前端异步解决方案-3(Promise)

genedna / 2747人阅读

摘要:又有好些天没有动笔了,这几天一直在断断续续的学习和,今天终于能够把着两个玩意结合起来了解决异步问题了。今天我先把相关的用法和对异步的处理分享给大家。老样子,还是先模拟一个。

又有好些天没有动笔了,这几天一直在断断续续的学习Promise和generator,今天终于能够把着两个玩意结合起来了解决异步问题了。今天我先把promise相关的用法和对异步的处理分享给大家。
老样子,还是先模拟一个Promise。

//咳咳这样就实现了嘛
let MyPromise = Promise;

开个玩笑,其实这两天我也一直在看Promise的实现,但是还是没有怎么理解。所以Promise的代码实现我暂时先放一放,等我完全理解再来新开一篇分享。这里先给大家推荐几篇我觉得比较好的Promise实现的博客,想要学习的小伙伴可以先到那边一睹为快,当然等我更新了之后大家还是要来给我文章点赞的哈。
彻底理解Promise对象——用es5语法实现一个自己的Promise(上篇)这一篇文章用的es5的语法,对es6不是很熟悉的同学可以用这篇文章顶一下
Promise实现原理(附源码)这一篇呢是用到了class的,所以需要大家对es6有所了解,也是一篇好文章

接下来我介绍一下Promise最常用的几个部分:

首先先介绍最简单的只有一个Promise对象的用法

//Promise()接收一个函数,并且在创建这个Promise对象的同时,接收的这个函数就会被立刻执行
var promise = new Promise(function (resolve, reject) {
  //resolve用来接收成功的返回,reject用来接收失败的返回
  setTimeout(function () {
    //这里我们生成一个随机数,并在接下来根据这个随机数的大小来判断这个异步是否成功
    let num = Math.random();
    if (num  > 0.8) {
      //接收失败的原因
      console.log("reject")
      reject(num + "大于0.8,这次异步操作失败了")
    } else {
      //接收成功的数据
      console.log("resolve")
      resolve(num + "小于0.8,这次异步操作成功了")
    }
  }, 100)
});
console.log("一个Promise对象生成了");
//Promise对象的.then()方法接收两个回调,第一个为成功回调,第二个为失败回调
//这两个回调会在上面的resolve或者reject函数生效后被调用
promise.then(function (data) {
  //这个函数会在上面的resolve函数被调用后生效,这里的data就是上面resolve()中接收的值
  console.log(data)
}, function (err) {
  ///这个函数会在上面的reject函数被调用后生效,这里的err就是上面reject()中接收的值
  console.error(err)
});
console.log("promise的.then方法被调用了")

大家可以按F12唤起控制台,然后把这段代码运行几次。看看会有什么结果;
多运行几次以后,大家应该可以看到这两类结果:


其中的undefind是console.log("promise的.then方法被调用了")这行代码的返回,大家可以不用关注。在这里可以看到不论是成功的结果还是失败的结果都是在定时器执行后再打印出来的。这种写法可以帮助我们实现简单的异步编程。

接下介绍多个Promise对象同时使用的用法, 先介绍最常见的.then()链式调用的方法

 //用来快速生成一个Promise对象,接收一个日志列表,不论成功还是失败都会往日志列表中添加一条日志
 function promise(log) {
   return new Promise(function (resolve, reject) {
     setTimeout(function () {
       log = log || [];
       //和上次的例子一样,利用随机数来随机失败和成功
       let num = Math.random();
       if (num > 0.5) {
         log.push(num + "大于0.5,这次异步操作失败了");
         reject(log)
       } else {
         log.push(num + "小于0.5,这次异步操作成功了");
         resolve(log)
       }
     }, 100)
   })
 }

.then()中返回了Promise对象的情况

var promise1 = promise();
//promise1.then()方法会返回一个Promise对象
//如果我们在.then()生效的那个 !!!回调方法!!! 中有返回一个Promise对象的话,该对象会被  !!!.then()方法!!!  返回

//先看返回了Promise对象的方式
promise1.then(function (data) {
  console.log(data);
  return promise(data)
}, function (err) {
  console.error(err);
  return promise(err)
}).then(function (data) {
  console.log(data)
}, function (err) {
  console.error(err)
});

这段代码运行后一共会有四种结果:
两次都成功

两次都失败

第一次失败,第二次成功

第一次成功,第二次失败

通过这种方法我们可以用比较清晰的方式来书写我们的异步代码。特别是多个异步操作嵌套的时候,可以链式调用.then()来实现,这样的代码看起来逻辑更清晰;
刚刚看完了返回了Promise对象的场景,再来看看没有返回Promise的场景

//如果我们没有返回Promise对象,.then()就会将我们返回的东西包装成一个Promise对象(没有返回就相当于返回了undefined)
//可以等同于我们写了 return new Promise((resolve,reject)=>{resolve(/*原先的返回值*/)})
promise1.then(function (data) {
  console.log(data);
  return data;
}, function (err) {
  console.error(err);
  return err;
}).then(function (data) {
  console.log(data)
}, function (err) {
  //这里是永远不会被触发的,原因是上一个.then() 返回的是new Promise((resolve,reject)=>{resolve(/*原先的返回值*/)})
  //返回的Promise对象的reject方法永远都不会被触发,所以这个里也就永远都不会触发了
  console.error(err)
});

讲解都写在注释里面了,接下里我就贴运行图吧,这段代码会运行出以下两类结果:

需要所有的请求都返回后才可以执行某个动作

//改造promise,让其可以接收一个定时器等待时间参数
function promise(log, time) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      log = log || [];
      //和上次的例子一样,利用随机数来随机失败和成功
      let num = Math.random();
      if (num > 0.5) {
        log.push("等待时长" + time + "," + num + "大于0.5,这次异步操作失败了");
        console.error(log);
        reject(log)
      } else {
        log.push("等待时长" + time + "," + num + "小于0.5,这次异步操作成功了");
        console.log(log);
        resolve(log)
      }
    }, time)
  })
}
//Promise.all()可以接收一个Promise对象的数组,返回一个Promise对象
//该Promise对象会在数组中所有Promise成功返回后执行成功回调,在任意一个Promise失败后立刻执行失败回调
var promise1 = promise(null, 10), promise2 = promise(null, 100),
  promise3 = Promise.all([promise1, promise2]);
promise3.then((data) => {
  //这里的data为promise1,和promise2的返回值的数组
  console.log("promise3", data)
}, (err, err2) => {
  //报错信息
  console.error("promise3", err)
});

这段代码一共有四种可能的结果
如果两次都成功的话

如果两次都成的话,promise3会执行成功回调,并且回调中的data就是promise1和promise2返回值的数组(数组顺序和.all()中的顺序一致)



任意一个promise失败的话,promise3会立刻执行失败回调,并且回调中的err就是失败的那个promise在reject中返回的值

文章写到这里,我认为Promise常用的一些用法都已经讲完了,更详细的Promise的教程请参考 MDN中对promise的讲解

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

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

相关文章

  • 前端原理_异步与单线程

    摘要:单线程什么是单线程语言的执行环境是单线程所谓单线程,就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。 单线程 什么是单线程? Javascript语言的执行环境是单线程(single thread) 所谓单线程,就是指一次只能完成一件任务。 如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。 执行JS代...

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

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

    cgspine 评论0 收藏0
  • 高级前端面试题大汇总(只有试题,没有答案)

    摘要:面试题来源于网络,看一下高级前端的面试题,可以知道自己和高级前端的差距。 面试题来源于网络,看一下高级前端的面试题,可以知道自己和高级前端的差距。有些面试题会重复。 使用过的koa2中间件 koa-body原理 介绍自己写过的中间件 有没有涉及到Cluster 介绍pm2 master挂了的话pm2怎么处理 如何和MySQL进行通信 React声明周期及自己的理解 如何...

    kviccn 评论0 收藏0
  • ES6-7

    摘要:的翻译文档由的维护很多人说,阮老师已经有一本关于的书了入门,觉得看看这本书就足够了。前端的异步解决方案之和异步编程模式在前端开发过程中,显得越来越重要。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。 JavaScript Promise 迷你书(中文版) 超详细介绍promise的gitbook,看完再不会promise...... 本书的目的是以目前还在制定中的ECMASc...

    mudiyouyou 评论0 收藏0

发表评论

0条评论

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