用了 Promise 其实并没有真正解决回调地狱问题,并且还新增了很多 .then(data => { .... }) 这些很没有意义的 “模板代码”。所以先人们又搞出了generator 和 async/await,generator 有一些很神奇的特性这个就不多说了,自己看 MDN 上的文档就好,但是 generator 也能挺方便地处理异步。

一、promise+迭代器=生成器

首先我们需要了解什么是迭代器( iterator),迭代就是指提供了统一的遍历复杂数据类型的方案。我们先回忆一下在内置对象中自带遍历器的有哪些?

  • Array
  • Set
  • Map
  • String
  • NodeList
  • 函数:arguments

使用迭代器的语法有(ES6):

  • for-of
  • ... 扩展运算符
        function forOf(arr,deal){
//拿到迭代器函数
let iteratorFn = arr[Symbol.iterator];
//迭代器函数调用得到迭代器,(注意保护内部this指向)
let it = iteratorFn.call(arr);
// console.log(it.next());//next方法调用得到“结果对象”,结果对象有两个属性:value 当前遍历到的元素,done 指示遍历完成的标志(值为true/false)
let resultObj;
while (!(resultObj = it.next()).done) {
console.log(resultObj.value);
}
}
forOf(arr,function(v){
console.log(v); })

再来看看生成器:

  1. function* genFn(){},生成器函数:function*
  2. let gen = genFn();,调用生成器函数 得到生成器
  3. gen.next(),生成器函数的next方法,将生成器函数进行分段调用

补充:

  • 结果对象,next()方法调用,不仅使函数分段调用了,还得到一个结果对象,包含value属性和done属性
  • yield,生成器函数分段的关键字,后面可以跟一个value值,就是结果对象的value值
        //生成器函数:function* yield   也可认为分段函数
function* genFn() {
console.log(1111);
yield 444;
console.log(2222);
yield 555;
console.log(3333); }
// //调用生成器函数 得到生成器
let gen = genFn();
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());
let resultObj;
while (!(resultObj = gen.next()).done) {
console.log(resultObj.value);
}

可以将yield看作分段,生成器函数中的的代码根据fn.next()调用次数来执行,调用几次则执行几段代码

二、ES7方法

1、关键字:

  • async:“所有”函数都可以加上async关键字变成一个异步函数;
  • await:只能使用在异步函数中,用来等待promise操作的promise.value

2、内容

  • 异步函数执行的结果是一个Promise对象,该对象受到函数返回值的影响,具体参照Promise.resolve(value)
  • 异步函数中的await关键字是有运算结果的,结果是一个Ptomise对象,该对象受到await后面的表达式影响,具体参照Promise.resolve(value)

现在有一个任务,有A,B,C,D四个步骤,其中D函数可以异步的得到一个结果,就是A函数想要的结果,怎么才能使A获得该结果?

思路:A---->B B---->C C---->D

首先我用比较粗暴的方法——回调函数来实现

        function a(){
b(function(data){
console.log(data);
})
}
function b(cd_b){
c(function(data){
cd_b(data)
})
}
function c(cd_c){
d(function(data){
cd_c(data)
})
}
function d(cd_d){
setTimeout(()=>{
let data = "彩虹"
cd_d(data)
},2000)
}
a();

这种回调需要将每一次传参的弄个清楚,非常麻烦,而且很容易让人包括自己阅读起来昏头,所以不建议使用这种方法,那么如果我们使用ES7的方法是否能简化代码,使其语义化增强呢?

        async function A() {
console.log(await B());
} async function B() {
return await C();
} async function C() {
return await D();
} async function D() {
return await new Promise((resolve) => {
setTimeout(() => {
let data = "彩虹"
resolve(data);
}, 3000)
})
} A();

可以看到,我们只需要将返回值获取,调用最顶层的函数就可以了,语义化比回调函数强上很多,也不存在传参混乱的问题了,这是一个非常方便的方法。

用ES7解决异步回调地狱问题的更多相关文章

  1. jquery.Deferred promise解决异步回调

    我们先来看一下编写AJAX编码经常遇到的几个问题: 1.由于AJAX是异步的,所有依赖AJAX返回结果的代码必需写在AJAX回调函数中.这就不可避免地形成了嵌套,ajax等异步操作越多,嵌套层次就会越 ...

  2. js中promise解决callback回调地狱以及使用async+await异步处理的方法

    1.callback回调地狱 function ajax(fn) { setTimeout(()=> { console.log('你好') fn() }, 1000) } ajax(() =& ...

  3. 利用Generator解决异步回调原理

    var i = 0; i++; function ajax(url){ return new Promise(function(resolve, reject){ setTimeout(functio ...

  4. async + promise 解决回调地狱

    // 解决异步回调地狱的方案: async + promise async function writeFile() {   // 打开文件   const fd = await new Promis ...

  5. Promise如何解决回调地狱

    为什么要有promise:解决(回调地狱)的问题 ### 回调地狱: ```js //跟以前的if条件地狱很像 // if(){ // if(){ // if(){ // } // } //} $.g ...

  6. 使用ES6的Promise完美解决回调地狱

    相信经常使用ajax的前端小伙伴,都会遇到这样的困境:一个接口的参数会需要使用另一个接口获取. 年轻的前端可能会用同步去解决(笑~),因为我也这么干过,但是极度影响性能和用户体验. 正常的前端会把接口 ...

  7. 深入了解Promise对象,写出优雅的回调代码,告别回调地狱

    深入浅出了解Promise 引言 正文 一.Promise简介 二.Promise的三种状态 三.函数then( ) 四.函数catch( ) 五.函数finally( ) 六.函数all( ) 七. ...

  8. js异步回调Async/Await与Promise区别 新学习使用Async/Await

    Promise,我们了解到promise是ES6为解决异步回调而生,避免出现这种回调地狱,那么为何又需要Async/Await呢?你是不是和我一样对Async/Await感兴趣以及想知道如何使用,下面 ...

  9. js中的回调函数 和promise解决异步操作中的回调地狱问题。

    回调函数 : 函数作为参数传递到另外一个函数中.简单数据类型和引入数据类型中的数组和对象作为参数传递大家肯定都不陌生,其实引用数据类型中的函数也是可以的. 事实上大家见到的很多,用到的也很多,比如jQ ...

随机推荐

  1. delphi 子窗体最大化

    procedure TForm2.FormCreate(Sender: TObject);begin perform(WM_SIZE,SIZE_MAXIMIZED,0);end; http://blo ...

  2. AOP 事物连接,记忆连接数据库,连接池

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www ...

  3. 前端——css属性方法

    目录 标签快捷写法 宽和高 字体 1.文字字体 2.字体大小 3.字体粗细 4.字体颜色 5.字体对齐 6.文字下划线控制 7.文字首行缩进 8.字体英文换大写 背景属性 1.背景颜色 2.背景图片 ...

  4. JDK源码系列(一) ------ 深入理解SPI机制

    什么是SPI机制 最近我建了另一个文章分类,用于扩展JDK中一些重要但不常用的功能. SPI,全名Service Provider Interface,是一种服务发现机制.它可以看成是一种针对接口实现 ...

  5. DOCKER学习_001:Docker简介

    一 Docker简介 1.1 docker由来 Docker的英文翻译是“码头工人”,即搬运工,它搬运的东西就是我们常说的集装箱Container,Container里面装的是任意类型的App.我们的 ...

  6. Hadoop集群分布式安装

    一 整体介绍 1.1 硬件环境 本文使用三台服务器搭建hadoop集群,使用Centos7.5系统,服务器均有独立ip 1.2 部署的软件 部署服务:namenode(HA),resourcemana ...

  7. 【题解】PKUWC2018简要题解

    [题解]PKUWC2018简要题解 Minimax 定义结点x的权值为: 1.若x没有子结点,那么它的权值会在输入里给出,保证这类点中每个结点的权值互不相同. 2.若x有子结点,那么它的权值有p的概率 ...

  8. $HDU1848\ Fibonacci\ again\ and\ again$ 博弈论

    正解:博弈论 解题报告: 传送门! 首先按照套路显然是考虑先预处理出所有数的$SG$函数值然后全局的$SG$就是$SG(n)$^$SG(m)$^$SG(p)$,这儿应该麻油问题$QwQ$? 然后就考虑 ...

  9. selenium模块的基本使用

    一.selenium库与requests库的区别 - selenium请求库: - 本质上是一个自动化测试模块; ---> 主要用于测试 UI界面 - selenium除了可以做自动化测试,还可 ...

  10. 【原创】够强!一行代码就修复了我提的Dubbo的Bug。

    这是 why 技术的第 28 篇原创文章 之前在<Dubbo 一致性哈希负载均衡的源码和 Bug,了解一下?>中写到了我发现了一个 Dubbo 一致性哈希负载均衡算法的 Bug. 对于解决 ...