用了 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. CP防火墙导入.csv格式的对象

    Step1:将.csv格式的对象上传到管理服务器,本例为/home/admin目录 [Expert@SZ-OFFICE-SMT:0]# pwd/home/admin[Expert@SZ-OFFICE- ...

  2. 不同RAM空间存储变量区分

  3. windows键的妙用

    (1)当你需要暂时离开电脑一会儿,怕其余人动你的电脑时,你只需要按windows键+L就可以了,当然前提是你给自己的电脑设置过开机密码. (2)有时候你需要在盘里边找某个文件,但你的桌面上密密麻麻的, ...

  4. DEVOPS技术实践_11:Jenkins集成Sonar

    前言 前面已经有介绍sonar的安装,简单应用,下面在简答的研究一下sonar和jenkins集成的简单使用,对于sonar的安装不做介绍 一 sonar的简单介绍 持续检查避免了低质量的代码,比如S ...

  5. 《带你装B,带你飞》pytest修炼之路1- 简介和环境准备

    1. pytest简介 pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,但是比unittest框架使用起来更简洁,效率更高.根据pytest的官方网站介 ...

  6. FPGA之IO信号类型深入理解

    在FPGA设计开发中,很多场合会遇到同一根信号既可以是输入信号,又可以是输出信号,即IO类型(Verilog定义成inout). 对于inout型的信号,我们既可以使用FPGA原语来实现,也可以使用V ...

  7. 洛谷P1248 加工生产调度 贪心

    正解:贪心 解题报告: 传送门$QwQ$ $umm$直接看可能比较难想,可以先考虑另一个题? 有$n$个小怪,每打一只小怪会扣$a_i$的血,打完之后会回升$b_i$的血,问至少要多少血量才能使全程血 ...

  8. 【汇编】2.第一个程序:hello world

    前言 在上篇博文 [汇编]1.汇编环境的搭建:DOSBox的安装 中,我们完成了 1.汇编环境模拟器DOSBox的安装. 2.汇编编译相关程序MASM6的下载. 在上篇文章的最后我们提到了挂载DOS程 ...

  9. Flink入门(五)——DataSet Api编程指南

    Apache Flink Apache Flink 是一个兼顾高吞吐.低延迟.高性能的分布式处理框架.在实时计算崛起的今天,Flink正在飞速发展.由于性能的优势和兼顾批处理,流处理的特性,Flink ...

  10. js中getBoundingClientrRect()方法的详解

    getBoundingClientRect(): 这个方法返回一个矩形对象,包含四个属性:left.top.right和buttom.分别表示元素各边与页面各边的距离 例如: var boxPosit ...