详解ES6中的三种异步解决方案


Posted in Javascript onJune 28, 2018

前置知识准备

  1. Generator 函数 执行会返回一个迭代器(Iterator), 在迭代器上可以调用  next() 方法, 执行下一个 yield  或 return
  2. 调用  next() 方法,会返回一个对象 {value: res, done: false} , value 的值 为 yield 之后表达式的值,done 的值 表示迭代器,是否已经执行完毕(最后一个yield  或 return )
  3. next() 方法,可以传入一个值,做为前一个yield 表达式的返回值

有了这些知识,可以把Promise 对象 做一个的 yield 的值,配合一个执行器,来处理异步操作

方式一: Generator + Promise + 执行器

const fs = require('fs')

// Promise 版的readFile
const readFile = function (fileName) {
 return new Promise(function(resolve, reject) {
  fs.readFile(fileName, function(err, data){
   if (err) return reject(error);
   resolve(data);
  })
 })
}

const gen = function * () {
 let f1 = yield readFile('a.txt');
 let f2 = yield readFile('b.txt');

 console.log('F1--->', f1.toString());
 console.log('F2--->', f2.toString());
}


// 基于 Generator 和 Promise 的自动执行器
function run(gen) {

 let g = gen();
 
 function next(data) {
  
  let result = g.next(data);

  if (result.done) return result.value;

  result.value.then(function(data) {
   next(data);
  });
 }
 next();
}

run(gen);

执行器 中的 result.value 现在是一个Promise, 通过 then 方法拿到需要的结果,传下一次 next 方法,这样 let f1 = yield readFile('a.txt');  就可以拿到值!

方式二:Generator + Thunk函数 + 执行器

const fs = require('fs')

// 把一个单一执行的函数 ,变成需要再次调用的函数,固定一部分参数
function thunkify(fn, obj = {}) {
  return function () {
    let args = Array.from(arguments);
    return function (m) {
      args.push(m)
      return fn.apply(obj, args)
    }
  }
}

const readFile = thunkify(fs.readFile, fs);

const gen = function* () {
  let f1 = yield readFile('a.txt');
  let f2 = yield readFile('b.txt');

  console.log('F1-->', f1.toString());
  console.log('F2-->', f2.toString());
}


// 基于 Generator 和 Thunk函数的自动执行器
function run(fn) {
  let gen = fn();

  function next(err, data) {
    let result = gen.next(data);
    if (result.done) return 1;
    result.value(next);
  }

  next();

}

run(gen);

这里的 Thunk 转换器,把原来的 fs.readFile 函数 转换成需要两次调用的函数 ,readFile 的执行结果,可以通过回调函数能参数传递出来,再传给 next 方法

方式三:基于 async 函数 和 await 的异步处理方式

const fs = require('fs')

// Promise 版的readFile
const readFile = function (fileName) {
 return new Promise(function(resolve, reject) {
  fs.readFile(fileName, function(err, data){
   if (err) return reject(err);
   resolve(data);
  })
 })
}

const asyncReadFile = async function () {
 const f1 = await readFile('a.txt');
 const f2 = await readFile('b.txt');
 console.log(f1.toString());
 console.log(f2.toString());
};

asyncReadFile();

readFile 函数 对比方式一没有大的变化 ,Generator 函数变成 了 async 函数,可见 这处方式 只是 方式一的一个语法糖,async 函数自带了执行器!

这个话题,还可以衍生出 yield 的更多用法 ,下次再写,欢迎关注我!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript 实用小技巧
Apr 07 Javascript
利用javaScript实现点击输入框弹出窗体选择信息
Dec 11 Javascript
jQuery中odd选择器的定义和用法
Dec 23 Javascript
基于javascript实现浏览器滚动条快到底部时自动加载数据
Nov 30 Javascript
基于AngularJs + Bootstrap + AngularStrap相结合实现省市区联动代码
May 30 Javascript
js 基础篇必看(点击事件轮播图的简单实现)
Aug 20 Javascript
微信小程序 本地存储及登录页面处理实例详解
Jan 11 Javascript
JS实现JSON.stringify的实例代码讲解
Feb 07 Javascript
jQuery实现 RadioButton做必选校验功能
Jun 15 jQuery
weex里Vuex state使用storage持久化详解
Sep 09 Javascript
Vue封装Swiper实现图片轮播效果
Feb 06 Javascript
移动端如何用下拉刷新的方式实现上拉加载
Dec 10 Javascript
Auto.js自动收取自己和好友蚂蚁森林能量脚本
Jun 28 #Javascript
使用vue-router完成简单导航功能【推荐】
Jun 28 #Javascript
vue如何引入sass全局变量
Jun 28 #Javascript
小程序实现带年月选取效果的日历
Jun 27 #Javascript
浅谈Angular6的服务和依赖注入
Jun 27 #Javascript
JS实现获取进今年第几天是周几的方法分析
Jun 27 #Javascript
vue+springmvc导出excel数据的实现代码
Jun 27 #Javascript
You might like
PHP中一些可以替代正则表达式函数的字符串操作函数
2014/11/17 PHP
使用PHP和JavaScript判断请求是否来自微信内浏览器
2015/08/18 PHP
php基于PDO实现功能强大的MYSQL封装类实例
2017/02/27 PHP
PHP中Static(静态)关键字功能与用法实例分析
2019/04/05 PHP
php实现session共享的实例方法
2019/09/19 PHP
JavaScript 拾碎[三] 使用className属性
2010/10/16 Javascript
functional继承模式 摘自javascript:the good parts
2011/06/20 Javascript
JavaScript Promise启示录
2014/08/12 Javascript
JS Array.slice 截取数组的实现方法
2016/01/02 Javascript
jquery mobile 实现自定义confirm确认框效果的简单实例
2016/06/17 Javascript
结合代码图文讲解JavaScript中的作用域与作用域链
2016/07/05 Javascript
JS中Array数组学习总结
2017/01/18 Javascript
JavaScript实现设置默认日期范围为最近40天的方法分析
2017/07/12 Javascript
node跨域转发 express+http-proxy-middleware的使用
2018/05/31 Javascript
webpack打包nodejs项目的方法
2018/09/26 NodeJs
layer.js open 隐藏滚动条的例子
2019/09/05 Javascript
基于Web Audio API实现音频可视化效果
2020/06/12 Javascript
Python yield 小结和实例
2014/04/25 Python
Python中为feedparser设置超时时间避免堵塞
2014/09/28 Python
解决Mac安装scrapy失败的问题
2018/06/13 Python
Python实现获取邮箱内容并解析的方法示例
2018/06/16 Python
css3和jquery实现的可折叠导航菜单适合放在手机网页的导航菜单
2014/09/02 HTML / CSS
使用jTopo给Html5 Canva中绘制的元素添加鼠标事件
2014/05/15 HTML / CSS
June Jacobs尊积帕官网:知名的spa水疗护肤品牌
2019/03/21 全球购物
小米官方旗舰店:Xiaomi
2020/08/07 全球购物
NULL是什么,它是怎么定义的
2015/05/09 面试题
为什么需要版本控制?
2013/08/08 面试题
学校办公室主任职责
2013/12/27 职场文书
工作表现评语
2014/01/19 职场文书
女儿十岁生日答谢词
2014/01/27 职场文书
三年级语文教学反思
2014/02/01 职场文书
《望洞庭》教学反思
2014/02/16 职场文书
卫校毕业生自我鉴定
2014/09/28 职场文书
驾驶员安全责任协议书
2016/03/22 职场文书
Oracle11g r2 卸载干净重装的详细教程(亲测有效已重装过)
2021/06/04 Oracle
MySQL 数据库 增删查改、克隆、外键 等操作
2022/05/11 MySQL