用了 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. TCP&IP基础概念复习

    第一章概述 NII(National Information Infrastructure):国家信息基础设施 GII(Global Information Infrastructure):全球信息基 ...

  2. DOCKER学习_008:Docker容器的运行最佳实践

    一 容器分类 容器按用途大致可分为两类: 服务类容器,如 web server. database等 工具类容器,如cur容器, Iredis-cli容器 通常而言,服务类容器需要长期运行,所以使用 ...

  3. js对当前时间进行处理

    //1.JS获取两个日期之间相差的天数 function getDaysBetween(dateString1, dateString2) { var startDate = Date.parse(d ...

  4. rest_framework框架下的Django声明和生命周期

    rest_framework框架下的Django声明和生命周期 Django声明周期(request) 客户端发起请求 请求经过wsgi wsgi: 是一个协议----web服务网关接口,即在web服 ...

  5. 1076 Wifi密码 (15 分)C语言

    下面是微博上流传的一张照片:"各位亲爱的同学们,鉴于大家有时需要使用 wifi,又怕耽误亲们的学习,现将 wifi 密码设置为下列数学题答案:A-1:B-2:C-3:D-4:请同学们自己作答 ...

  6. Selenium python爬虫

    Selenium + Python3 爬虫 准备工作 Chrome驱动下载地址(可正常访问并下载),根据自己chrome的版本下载 Chrome版本 下载地址 78 https://chromedri ...

  7. Google 开源的 Python 命令行库:深入 fire(二)

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

  8. 微信小程序开发笔记(二)

    一.前言 继承上一篇所说的,有了对微信小程序的基础概念后,这边将会示范动手做一个小程序,在动手的过程中我们可以更快的熟悉小程序里面的架构和开发流程. 二.小程序的设计 这次要做的是一个猜数字的程序,程 ...

  9. 4.eclipse中导入别人用的源代码问题

    最近在导入别人用的源代码问题时,出现两个问题: 问题一:提示无法解析导入,如下图: 解决方法:删除项目下的module-info.java文件即可,或者在创建项目时将创建module-info.jav ...

  10. angular.foreach 循环方法

    angular循环给一个 angular监听的变量复值时.最好还是用angular自带的循环方法.“angular.foreach” 尽量避免代码的冲突,最好不要jq angular 混用 var o ...