es6——promise(解决回调地狱的问题)及 jQuery 中的 promise 应用
2018-10-28 11:54
806 查看
版权声明:未经同意,不得随意转载转载 https://blog.csdn.net/lucky541788/article/details/83473401
注意:里面一些执行报错结果,是为了演示,故意写错地址
1. 首先,提出一个需求:要封装一个方法,使得能够读取文件,并将内容返回
先创建 3个 .txt 文件
1.txt/2.txt/3.txt,作为我们要读取的文件,内容自己瞎编
- fs 和 path 模块:
const fs = require('fs'); const path = require('path');
- 这是普通读取文件的方式:
fs.readFile(path.join(__dirname, './files/1.txt'), 'utf-8', (err, dataStr) => { if (err) throw err; console.log(dataStr); });
- 升级:
我们可以规定一下,callback 中,有两个参数,第一个参数,是失败的结果;第二个参数是成功的结果
同时规定:如果成功后,返回的结果,应该位于 callback 参数的第二个位置,此时,第一个位置由于没有出错,所以放一个 null;如果失败了,则第一个位置放置 Error 对象,第二个位置放置 undefined
function readFile(fpath, callback) { fs.readFile(fpath, 'utf-8', (err, dataStr) => { // 如果报错了,则进入 if 分支 if (err) return callback(err); // return 会返回 undefined // return dataStr; callback(null, dataStr); }) } /*var result = readFile(path.join(__dirname, './files/1.txt')); console.log(result);*/ readFile(path.join(__dirname, './files/1.txt'), (err, dataStr) => { // console.log(dataStr); if (err) return console.log(err.message); console.log(dataStr); });
2. 其次,需求升级:先读取文件1,再读取文件2,最后读取文件3
const fs = require('fs'); const path = require('path'); // 为了方便初学者理解,在这里我把原来 callback 分为 succCB 和 errCB function getFileByPath(fpath, succCB, errCB) { fs.readFile(fpath, 'utf-8', (err, dataStr) => { if (err) return errCB(err); succCB(dataStr); }) }
- 好了,见证回调地狱的时候到了:由于现在是读取三个文件,可能没什么,假如一万个文件。。。。。。呵呵
// 回调地狱 getFileByPath(path.join(__dirname, './files/1.txt'), function (data) { console.log(data); getFileByPath(path.join(__dirname, './files/2.txt'), function (data) { console.log(data); getFileByPath(path.join(__dirname, './files/3.txt'), function (data) { console.log(data); }); }); });
3. 现在引入主题:Promise
使用 ES6 中的 Promise,来解决回调地狱的问题;
注意:promise 只是单纯的解决回调地狱问题,并不是解决代码量;
- Promise 是一个构造函数,可以 new Promise() 得到一个 Promise 的实例;
- 在 Promise 上,有两个函数,分别叫做 resolve(成功后的回调函数) 和 reject(失败后的回调函数)
- 在 Promise 构造函数的 Prototype 属性上,有一个 .then() 方法,也就是说,只要是 Promise 构造函数创建的实例,都可以访问到 .then() 方法
- Promise 表示一个异步操作;每当我们 new 一个 Promise 的实例,这个实例,就表示一个具体的异步操作;
- 既然 Promise 创建的实例,是一个异步操作,那么这个异步操作的结果,只能有两种状态:
-
状态1:异步执行成功了,需要在内部调用 成功的回调函数 resolve 把结果返回给调用者;
- 状态2:异步执行失败了,需要在内部调用 失败的回调函数 reject 把结果返回给调用者;
- 由于 Promise 的实例,是一个异步操作,所以,内部拿到操作的结果后,无法使用 return 把操作结果返回给调用者;这时候,只能使用回调函数的形式,来把成功或失败的结果,返回给调用者;
- 可以在 new 出来的 Promise 实例上,调用 .then() 方法,【预先】为这个 Promise 异步操作,指定 成功(resolve) 和 失败(reject) 回调函数;
下面代码解释原理:
1
// 注意:这里 new 出来的 promise,只是代表 【形式上】的一个异步操作(空壳); let promise = new Promise();
2
const fs = require('fs'); // 每当 new 一个 promise 实例的时候,就会立即执行这个异步操作中的代码 // 也就是说,new 的时候,除了能够得到一个 promise 实例之外,还会立即调用我们 // 为 Promise 构造函数传递的那个function,执行这个 function 中的异步操作代码; let promise = new Promise(function () { fs.readFile('./files/3.txt', 'utf-8', (err, dataStr) => { if (err) throw err; console.log(dataStr); }) });
3
const fs = require('fs'); // 可以自己决定是否调用 Promise function getFileByPath(fpath) { let promise = new Promise(function () { fs.readFile(fpath, 'utf-8', (err, dataStr) => { if (err) throw err; console.log(dataStr); }) }) } getFileByPath('./files/3.txt');
4
const fs = require('fs'); // 可以报具体错误 function getFileByPath(fpath) { let promise = new Promise(function (resolve, reject) { //*2 fs.readFile(fpath, 'utf-8', (err, dataStr) => { /*if (err) throw err; console.log(dataStr);*/ if (err) reject(err); resolve(dataStr); }) }); return promise; } let p=getFileByPath('./files/.txt'); // 第一个是 resolve,第二个是 reject //*1 p.then(function (data) { console.log('执行成功:'+data); },function (err) { console.log('执行失败:'+err.message); });
注意:执行步骤是先
*1再
*2
// 优化写法 getFileByPath('./files/.txt').then(function (data) { console.log('执行成功:' + data); }, function (err) { console.log('执行失败:' + err.message); });
解决回调地狱的问题:
const fs = require('fs'); function getFileByPath(fpath) { let promise = new Promise(function (resolve, reject) { fs.readFile(fpath, 'utf-8', (err, dataStr) => { if (err) reject(err); resolve(dataStr); }) }); return promise; } // 注意:通过 .then 指定回调函数的时候,成功的函数, // 必须传,但是失败的回调可以省略 // 在上一个 .then 中,返回一个新的 promise 实例,可以继续用下一个 .then 来处理 getFileByPath('./files/1.txt') .then(function (data) { console.log(data); // 读取文件2,下面的以此类推 return getFileByPath('./files/2.txt') }) .then(function (data) { console.log(data); return getFileByPath('./files/3.txt') }) .then(function (data) { console.log(data); });
如果前面的 Promise 执行失败,我们不想让后续的 Promise 操作被终止,可以为每个 Promise 指定失败的回调
getFileByPath('./files/.txt') .then(function (data) { console.log(data); // 读取文件2,下面的以此类推 return getFileByPath('./files/2.txt') }, function (err) { console.log('这是失败的结果:' + err); // 读取文件2,下面的以此类推 return getFileByPath('./files/2.txt') }) .then(function (data) { console.log(data); return getFileByPath('./files/3.txt') }) .then(function (data) { console.log(data); });
如果后续的 Promise 执行,依赖于前面 Promise 执行的结果,如果前面的失败了,则后面的就没有执行下去的意义了,实现一旦有报错,则立即终止所有 Promise 的执行
getFileByPath('./files/1.txt') .then(function (data) { console.log(data); // 读取文件2,下面的以此类推 return getFileByPath('./files/.txt') }) .then(function (data) { console.log(data); return getFileByPath('./files/3.txt') }) .then(function (data) { console.log(data); }) .catch(function (err) { // catch 的作用:如果前面有任何的 Promise 执行失败,则立即终止所有 // 的 Promise 的执行,并立即进入 catch 去处理 Promise 中抛出的异常; console.log('这是自己的处理方式:' + err.message); });
jQuery 中的 promise 应用
$(function () { $('#btn').on('click', function () { $.ajax({ url: './data.json', type: 'get', dataType: 'json' /*success: function (data) { console.log(data); }*/ }) // 不用 success 而是使用 promise 中的 .then .then(function (data) { console.log(data); }) }) })阅读更多
相关文章推荐
- javascript异步代码的回调地狱以及JQuery.deferred提供的promise解决方式
- 使用ES6的Promise完美解决回调地狱
- 使用ES6的Promise完美解决回调地狱
- 使用ES6的Promise完美解决回调地狱
- 使用ES6的Promise完美解决回调地狱
- 再不用ES6就Out了--Promise解决回调地狱
- 分享回调地狱的体现与利用es6 Promise对回调的改良和实现
- Promise解决node.js回调问题
- jQuery应用load()方法后js失效的问题分析与解决
- 如何解决回调地狱问题(任何语言)
- 通过ES6中通过promise处理回调函数问题
- Angular使用Promise解决多个异步回调问题
- JQuery问题集锦:使用jquery中的each函数时,需要break、continue的应用场景解决办法
- 深入理解Promise框架(解决js中的回调地域问题!)
- jquery Deferred 快速解决异步回调的问题
- jquery Deferred 快速解决异步回调的问题
- 【前端JQuery】回调获取json中包含换行符出现问题解决
- 使用Promise 和 $.Deferred 解决js回调地狱
- 应用UpdatePanel后jQuery事件失效问题的解决方法
- ES6 Promise对象解决异步回调