热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[前端座谈_2]从Dva的Effect到Generator+Promise完成异步编程

你能学到什么怎样应用Generator+Promise完成异步编程异步编程的道理剖析媒介连系上一篇文章,我们来聊聊Generator基础道理说到异步编程,你想到的是async和aw

你能学到什么

  • 怎样应用 Generator + Promise 完成异步编程
  • 异步编程的道理剖析

媒介

连系 上一篇文章 ,我们来聊聊 Generator

基础道理

说到异步编程,你想到的是asyncawait ,但那也只是 Generator 的语法糖罢了。dva 中有一个 Effect 的观点,它就是应用 Generator 来处置惩罚异步要求的题目,我们也来聊一聊 Generator + Promise 怎样异步编程:

最先之前,我们须要相识一些基础的观点:

  • Generator作为 ES6 中应用协程的处置惩罚方案来处置惩罚异步编程的详细完成,它的特点是: Generator 中能够应用 yield 症结字合营实例 gen 挪用 next() 要领,来将其内部的语句支解实行。 简言之 : next() 被挪用一次,则 yield 语句被实行一句,跟着 next() 挪用, yield 语句被顺次实行。
  • Promise示意一个异步操纵的终究状况(完成或失利),以及其返回的值。参考Promise-MDN

所以,异步编程应用 GeneratorPromise 来完成的道理是什么呢?

  1. 由于 Generator 自身 yield 语句是星散实行的,所以我们应用这一点,在 yield 语句中返回一个 Promise 对象
  2. 初次挪用 Generator 中的 next() 后, 假定返回值叫 result ,那末此时 result.value 就是我们定义在 yield 语句中的 Promise 对象

注重:在这一步,我们已把本来的实行流程停息,转而实行 Promise 的内容,已完成了掌握异步代码的实行,由于此时我们假如不继承实行 next()generator 中位于当前被实行的 yield 背面的内容,将不会继承实行,这已达到了我们须要的效果

  1. 接下来我们就是在实行完当前 Promise 以后,让代码继承往下实行,直到碰到下一个 yield 语句:

    这一步是最症结的 所以我们怎么做呢:

    步骤1: 在当前的 Promisethen() 要领中,继承实行 gen.next()

    步骤2: 当 gen.next() 返回的效果 result.dOne=== true 时,我们拿到 result.value【也就是一个新的 Promise 对象】再次实行而且在它的then() 要领中继承上面的步骤1,直至 result.dOne=== false 的时刻。这时刻挪用 resolve() 使 promise 状况转变,由于一切的 yield 语句已被实行完。

    • 步骤1 保证了我们能够走到下一个 yield 语句
    • 步骤2 保证了下一个 yield 语句实行完不会中缀,直至 Generator 中的末了一个 yield 语句被实行完。

流程示意图:

《[前端座谈_2] 从 Dva 的 Effect 到 Generator + Promise 完成异步编程》

详细完成

co 是有名大神
TJ 完成的
Generator 的二次封装库,那末我们就从
co库中的一个demo最先,相识我们的全部异步要求封装完成:

co(function*() {
yield me.loginAction(me.form);
...
});

在这里我们引入了co库,而且用co来包裹了一个generator(生成器)对象。

接下来我们看下co关于包裹起来的generator做了什么处置惩罚

function co(gen) {
// 1.猎取当前co函数的实行上下文环境,猎取到参数列表
var ctx = this;
var args = slice.call(arguments, 1);
// 2.返回一个Promise对象
return new Promise(function(resolve, reject) {
// 推断而且应用ctx:context(上下文环境)和arg:arguments(参数列表)初始化generator而且复制给gen
// 注重:
// gen = gen.apply(ctx, args)以后
// 我们挪用 gen.next() 时,返回的是一个指针,现实的值是一个对象
// 对象的情势:{done:[false | true], value: ''}
if (typeof gen === 'function') gen = gen.apply(ctx, args);
// 当返回值不为gen时或许gen.next的范例不为function【现实是推断是不是为generator】时
// 当前promise状况被设置为resolve而完毕
if (!gen || typeof gen.next !== 'function') return resolve(gen);
// 不然实行onFulfilled()
onFulfilled();
});
}

总结一下这里发生了什么

  1. 返回一个 promise
  2. promise 中将被包裹的 generator 实例化为一个指针,指向 generator 中第一个 yield 语句
  3. 推断 generator 实例化出来的指针是不是存在:假如没有 yield 语句则指针不存在
    推断指针 gen.next() 要领是不是为 function :假如不为 function 证实没法实行 gen.next()
    前提有一项不满足就将 promise 的状况置为 resolve
    不然实行 onFulfilled()

接下来我们看下 onFulfilled() 的完成

function onFulfilled(res) {
// 在实行onFulfilled时,定义了一个ret来贮存gen.next(res)实行后的指针对象
var ret;
try {
ret = gen.next(res);
// 在这里,yield语句抛出的值就是{value:me.loginAction(me.form), done:false}
} catch (e) {
return reject(e);
}
// 将ret对象传入到我们定义在promise中的next要领中
next(ret);
return null;
}

总结一下,onFulfilled 最重要的事变就是

  1. 实行 gen.next() 使代码实行到 yield 语句
  2. 将实行后返回的效果传入我们自定义的 next() 要领中

那末我们再来看 next() 要领

function next(ret) {
// 进入next中起首推断我们传入的ret的done状况:
// 状况1:ret.dOne= true 代表我们这个generator中一切yield语句都已实行完。
// 那末将ret.value传入到resolve()中,promise的状况变成处置惩罚,全部历程完毕。
if (ret.done) return resolve(ret.value);
// 状况2:当前ret.dOne= false 代表generator还未将一切的yield语句实行完,那末这时刻
// 我们把当前上下文和ret.value传入toPromise中,将其转换为对应的Promise对象`value`
var value = toPromise.call(ctx, ret.value);
if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
// 当value确实是一个promise对象的时刻,return value.then(onFulfilled,onRejected)
// 我们从新进入到了generator中,实行下一条yield语句
return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, '
+ 'but the following object was passed: "' + String(ret.value) + '"'));
}

总结一下,next 重要事变

  1. 推断上一次 yield 语句的实行效果
  2. yieldresultvalue 值【实在就是我们要异步实行的 Promise
  3. 实行 valuethen 要领,从新进入到 onFulfilled 要领中,而在 onFulfilled 中,我们又将进入到当前要领,云云轮回的挪用,完成了 generatorPromise 的实行切换,从而完成了 Promise 的内容依据我们所定义的递次实行。

有同砚可能对这里的 toPromise 要领有一些迷惑,我先把代码贴出来

function toPromise(obj) {
if (!obj) return obj;
if (isPromise(obj)) return obj;
if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj);
if ('function' == typeof obj) return thunkToPromise.call(this, obj);
if (Array.isArray(obj)) return arrayToPromise.call(this, obj);
if (isObject(obj)) return objectToPromise.call(this, obj);
return obj;
}

实在这个函数做的事变就是,依据差别的范例举行转换,使得末了输出的范例都是一个 Promise。那详细的转换细节,人人能够参考co库的源码。

至此完成异步操纵的掌握。

末了

这里是 Dendoink ,奇舞周刊原创作者,掘金 [团结编辑 / 小册作者] 。
关于手艺人而言:技 是单兵作战才能,术 则是应用才能的要领。随心所欲,炉火纯青就是 艺 。在前端娱乐界,我想成为一位精彩的群众艺术家。扫码关注民众号 前端恶霸 我在这里等你:

《[前端座谈_2] 从 Dva 的 Effect 到 Generator + Promise 完成异步编程》


推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
author-avatar
白羊座的张康安_3z2_381
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有