一、前言

通过这个例子对promise解决回调地狱问题有一个初步理解。

二、主要内容

1、回调地狱:如下图所示,一个回调函数里面嵌套一个回调函数,这样的代码可读性较低也比较恶心

2、下面用一个简单的例子来体验回调

      举例:我们想要按照顺序读取三个文件,a.txt  b.txt  c.txt  通过已经学的知识,发现下面的代码是不行的(代码是在node环境中实现)

(1)项目目录结构如下:

(2)callback.js: 如下

var fs = require('fs');
//读取文件a.txt
fs.readFile('./data/a.txt', function (err, data) {
if (err) {
throw err
} console.log(data.toString());
}) //读取文件b.txt
fs.readFile('./data/b.txt', function (err, data) {
if (err) {
throw err
} console.log(data.toString());
}) //读取文件c.txt
fs.readFile('./data/c.txt', function (err, data) {
if (err) {
throw err
} console.log(data.toString());
})

(3)测试:发现读取文件的顺序并不是先a.txt --> b.txt -->c.txt,因为这里读取文件是异步的,这里执行的顺序取决于文件的大小

(4)为了让读取的文件按照顺序来,我们可以用一下嵌套的方式 ,这种方式可以保证读取的顺序是按照a b c顺序来的,,但是代码嵌套得比较恶心,,这里只有三层嵌套,

var fs = require('fs');
//读取a.txt
fs.readFile('./data/a.txt', function (err, data) {
if (err) {
throw err
} console.log(data.toString());
//读取b.txt
fs.readFile('./data/b.txt', function (err, data) {
if (err) {
throw err
} console.log(data.toString());
//读取c.txt
fs.readFile('./data/c.txt', function (err, data) {
if (err) {
throw err
} console.log(data.toString());
}) })
})

 3、使用promise来解决回调嵌套(不了解promise的可以参照阮一峰老师的es6文档)

var fs = require('fs')

//创建p1的promise容器
var p1 = new Promise(function (resolve, reject) {
fs.readFile('./data/a.txt', 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})

//创建p2的promise容器
var p2 = new Promise(function (resolve, reject) {
fs.readFile('./data/b.txt', 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})

//创建p3的promise容器
var p3 = new Promise(function (resolve, reject) {
fs.readFile('./data/c.txt', 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})

p1
.then(function (data) {
console.log(data)
// 当 p1 读取成功的时候
// 当前函数中 return 的结果就可以在后面的 then 中 function 接收到
// 当你 return 123 后面就接收到 123
// return 'hello' 后面就接收到 'hello'
// 没有 return 后面收到的就是 undefined
// 真正有用的是:我们可以 return 一个 Promise 对象
// 当 return 一个 Promise 对象的时候,后续的 then 中的 方法的第一个参数会作为 p2 的 resolve
//
return p2
}, function (err) {
console.log('读取文件失败了', err)
})
.then(function (data) {
console.log(data)
return p3
})
.then(function (data) {
console.log(data)
console.log('end')
})

为什么可以那样做:

 4、将上面的方法封装

var fs = require('fs')

function pReadFile(filePath) {
return new Promise(function (resolve, reject) {
fs.readFile(filePath, 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
} pReadFile('./data/a.txt')
.then(function (data) {
console.log(data)
return pReadFile('./data/b.txt')
})
.then(function (data) {
console.log(data)
return pReadFile('./data/c.txt')
})
.then(function (data) {
console.log(data)
})

三、总结

参考:阮一峰:http://es6.ruanyifeng.com

ES6(promise)_解决回调地狱初体验的更多相关文章

  1. ES6(promise)_解决回调嵌套简单应用

    一.前言 这个小案例是在node平台上应用的所以需要保证你的电脑: 1.安装和配置node.js环境 2.需要用node.js来开启一个http-server: 开启方法:https://blog.c ...

  2. promise对象解决回调地狱

    先放一张图片感受一下回调地狱 看起来是真的很让人头痛的东西 而现在我这里使用promise对象来解决回调地狱 采用链式的 then,可以指定一组按照次序调用的回调函数. 这时,前一个 then 里的一 ...

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

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

  4. 【JavaScript】 使用Async 和 Promise 完美解决回调地狱

    很久以前就学习过Async和Promise,但总是一知半解的. 今天在写NodeJS的时候,发现好多第三方库使用回调,这样在实际操作中会出现多重回调,这就是传说中的JS回调地狱. 举个例子 有一个方法 ...

  5. Promise如何解决回调地狱

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

  6. 回调地狱以及用promise怎么解决回调地狱

    哈哈哈,我又又又回来了,不好意思,最近枸杞喝的比较到位,精力比较旺盛. 现在我们来聊一聊啥是回调地狱,注意是回调地狱啊   不是RB人民最爱拍的那啥地狱啊,来吧,上车吧少年,这是去幼儿园的车 都让开, ...

  7. 基于PROMISE解决回调地狱问题

    回调地狱问题: 在使用JavaScript时,为了实现某些逻辑经常会写出层层嵌套的回调函数,如果嵌套过多,会极大影响代码可读性和逻辑,这种情况也被成为回调地狱.比如说你要把一个函数 A 作为回调函数, ...

  8. Promise,async/await解决回调地狱

    先说一下async的用法,它作为一个关键字放到函数前面,用于表示函数是一个异步函数,因为async就是异步的意思, 异步函数也就意味着该函数的执行不会阻塞后面代码的执行. 写一个async 函数 as ...

  9. async + promise 解决回调地狱

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

随机推荐

  1. 学习 Spring (十三) AOP 配置

    Spring入门篇 学习笔记 Spring 所有的切面和通知器都必须放在一个 内(可以配置包含多个 元素),每一个 可以包含 pointcut, advisor 和 aspect 元素(它们必须按照这 ...

  2. 进程创建fork()

    简单进程创建例子: #include <stdio.h> #include <sys/types.h> #include <sys/wait.h> #include ...

  3. Druid简单使用

    一.添加maven依赖 <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <depende ...

  4. load加载层-layui

    加载样式 //eg1 var index = layer.load(); //eg2 var index = layer.load(1); //换了种风格 //eg3 var index = laye ...

  5. js中session操作

    // 保存数据到sessionStorage sessionStorage.setItem('key', 'value');   // 从sessionStorage获取数据 var data = s ...

  6. yum的使用与配置

    yum简介 yum,是Yellow dog Updater, Modified 的简称,是杜克大学为了提高RPM 软件包安装性而开发的一种软件包管理器.起初是由yellow dog 这一发行版的开发者 ...

  7. BZOJ3133[ballmachine]——倍增+优先队列

    题目描述 有一个装球机器,构造可以看作是一棵树.有下面两种操作: 从根放入一个球,只要下方有空位,球会沿着树滚下.如果同时有多个点可以走,那么会选择编号最小的节点所在路径的方向.比如依次在树根4放2个 ...

  8. Dijkstra—校园景点游览问题

    #include<iostream> #include<cstdio> #include<cstring> #define MAX 9999999 using na ...

  9. Educational Codeforces Round 58 A,B,C,D,E,G

    A. Minimum Integer 链接:http://codeforces.com/contest/1101/problem/A 代码: #include<bits/stdc++.h> ...

  10. ans Single VIP LLB and SLB config

    ans Single VIP LLB and SLB config 配置命令: # 配置设备工作模式和开启的功能 > enable ans mode FR MBF Edge USNIP L3 P ...