详解ES7的async及webpack配置async

版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/article/details/78210599

项目中有个需求,类似视频网站下载视频,比如有5个case,每个case有数量不等的的video需要从服务端下载,并且video的下载顺序是串联的,只有当正在下载的case下载完才能下载另外一个case,否则下一个case处于wait状态。

如何解决此问题

  • 使用Promise 利用promise的then方法,但是因为无法确定每个case的video的数量,导致不能确定后面应该接几个then,最开始想到一个笨方法,列一个表格把所有可能的video数量都列出来(因实际需求每个case不会超过10个video),然后去套用不同的方法,
function downVideoSeries(n) {
  if(n === 1) {
    return new Promise((resolve, reject) =>{
      //ajax code for one video
    }).then((resolve)=>{
      ...
    }).catch((err)=>{
      ...
    })
  }else if(n ===2) {
    return new Promise((resolve, reject) =>{
      //ajax code for one video
    }).then((resolve)=>{
      new Promise((resolve, reject) =>{
        //ajax code for another video
      })
    }).then((resolve)=>{
      ...
    }).catch((err)=>{
      ...
    })
  }
  ...
}

后经重新查看Promise,可以发现能构造一个空的Promise来解决问题,动画一帧帧执行的代码

function chainAnimationsPromise(elem, animations) {

  // 变量ret用来保存上一个动画的返回值
  let ret = null;

  // 新建一个空的Promise
  let p = Promise.resolve();

  // 使用then方法,添加所有动画
  for(let anim of animations) {
    p = p.then(function(val) {
      ret = val;
      return anim(elem);
    });
  }

  // 返回一个部署了错误捕捉机制的Promise
  return p.catch(function(e) {
    /* 忽略错误,继续执行 */
  }).then(function() {
    return ret;
  });

}
  • 流程控制终极大法: async

async会将其后的函数(函数表达式或lamada)的返回值封装成一个Promise对象,所以获取async返回值用then调用。

async中的await用同步的方式来执行异步流,并且是阻塞的,只有当前的await执行,流程才会走向下一个。很适合此项目需求,因之前未用过,故配置webpack也遇到了坑。类似代码

async startDownPerCase() {
try{
     for(let i=0; i<len; i++) {
       let url = 'xhr.url';
       //异步请求
       await self.doBlobGet(url, ...args)
       .then(()=>{
         //成功回调
         ....
       }).catch((err)=>{
         //失败回调
         ...
       });
     }
   } catch(e) {
     console.log(`[downPerCaseError], ${e}`);
   }
}

在react+webpack中使用async

项目架构为webpack+react+es6。未配置的情况下,执行会输出错误提示Babel 6 regeneratorRuntime is not defined,查阅stackoverflow,需要进行配置

  • npm install babel-preset-stage-3 和 npm install babel-polyfill
  • webpack.config.js中entry添加 [‘babel-polyfill’, __dirname + ‘/router.js’]
  • bable的presets设置为presets: ['es2015', 'stage-3', 'react']
  • eslint设置为如下,把版本改成8,保证不报error错误
"parserOptions": {
        "ecmaVersion": 8,
        "sourceType": "module",
        "ecmaFeatures": {
            "jsx": true
        }
    }

还有另外一种解决方案,使用 babel-plugin-transform-runtime

参考 https://stackoverflow.com/questions/33527653/babel-6-regeneratorruntime-is-not-defined

async的用法

async函数返回一个 Promise 对象,可以使用then方法添加回调函数

返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数

function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}

asyncPrint('hello world', 50);

await 命令

正常情况下,await命令后面是一个 Promise 对象。如果不是,会被转成一个立即resolve的 Promise 对象。

async function f() {
  return await 123;
}

f().then(v => console.log(v))
// 123

只要一个await语句后面的 Promise 变为reject,那么整个async函数都会中断执行。

async function f() {
  await Promise.reject('出错了');
  await Promise.resolve('hello world'); // 不会执行
}

所以一般会使用try catch来捕获错误

async function f() {
  try {
    await new Promise().then(()=>{}).catch(()=>{});
  } catch(e) {
  }
  return await Promise.resolve('hello world');
}

如果有多个await命令,可以统一放在try…catch结构中。

async function main() {
  try {
    const val1 = await firstStep();
    const val2 = await secondStep(val1);
    const val3 = await thirdStep(val1, val2);

    console.log('Final: ', val3);
  }
  catch (err) {
    console.error(err);
  }
}

async语法参考阮一峰大神写的http://es6.ruanyifeng.com/#docs/async#基本用法

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏C/C++基础

Linux命令(32)——grep命令

grep(Globally search a Regular Expression and Print)是GNU开发的一款免费开源的文本搜索工具。grep家族包...

1513
来自专栏Java架构师历程

java基础复习

Java是一个支持并发、基于类和面向对象的计算机编程语言。下面列出了面向对象软件开发的优点:

3402
来自专栏http://www.cnblogs.com

第一周作业-三级菜单

image.png 1. 运行程序输出第一级菜单 2. 选择一级菜单某项,输出二级菜单,同理输出三级菜单 3. 菜单数据保存在文件中 4. 让用户选择是否要退出...

37210
来自专栏逆向技术

异常处理第三讲,SEH(结构化异常处理),异常展开问题

           异常处理第三讲,SEH(结构化异常处理),异常展开问题 不知道昨天有木有小伙伴尝试写一下SEH异常处理的代码.如果没写过,请回去写( :...

23310
来自专栏运维小白

linux基础(day26)

9.1正则介绍_grep(上) 正则介绍 正则就是一串有规律的字符串 掌握好正则对编写shell脚本帮助交大 各种编程语言中都有正则,原理是一样的 grep/e...

24810
来自专栏http://www.cnblogs.com

shelve模块

shelve是一个简单的数据存储方案,类似key-value数据库,可以很方便的保存python对象,其内部是通过pickle协议来实现数据序列化。shelve...

37217
来自专栏GreenLeaves

Jquery filter()方法简介

利用filter函数可以从wrapper set中过滤符合条件的dom元素。 如下图html代码,假如我们要获取类名为filter的<a>标签,用filter方...

2059
来自专栏IMWeb前端团队

Zepto源码分析之ie模块

本文作者:IMWeb 谦龙 原文出处:IMWeb社区 未经同意,禁止转载 前言 ? Zepto中的ie模块主要是改写getComputedStyle...

1978
来自专栏coding...

swift3.0 基础练习-实现99乘法表

723
来自专栏北京马哥教育

Linux Bash脚本15分钟进阶教程

这里的技术技巧最初是来自谷歌的“Testing on the Toilet” (TOTT)。这里是一个修订和扩增版本。

730

扫码关注云+社区

领取腾讯云代金券