解决回调地狱问题

  比如我们现在有个读取文件的需求,那么用nodejs,刚开始我们的代码会这么写
  
  var fs=require('fs');
  
  var path=require('path');
  
  function readFile(fpath){
  
  fs.readFile(fpath,'utf-8',(err,data)=>{
  
  if(err) throw err;
  
  return data;
  
  })
  
  }
  
  let res=readFile('App.vue');
  
  //这里打印为undefined 因为fs.readFile是异步的,主线程在遇到异步函数时,会将异步任务放到队列中,然后
  
  //继续执行,所以这里得到undefined
  
  console.log(res);
  
  解决思路1:利用回调函数,获取异步结果
  
  function readFile(fpath,callback){
  
  fs.readFile(fpath,'utf-8',(err,data)=>{
  
  if(err) throw err;
  
  throw new Error('er hui');
  
  callback(data);
  
  })
  
  }
  
  //但这里又存在一个问题,如果这个函数经常发生异常,这样的话,通过回调还是拿不到结果的,
  
  //我们应该将处理的结果告诉给调用者,由调用者决定要如果处理结果,包括异常结果
  
  readFile('App.vue',result=>{
  
  console.log(result)
  
  });
  
  改进如下,将回调函数定义成有两个参数:
  
  function readFile(fpath,callback){
  
  fs.readFile(fpath,'utf-8',(err,data)=>{
  
  if(err) callback(err);
  
  callback(null,data);
  
  })
  
  }
  
  //但这里又存在一个问题,如果这个函数经常发生异常,这样的话,通过回调还是拿不到结果的,
  
  //我们应该将处理的结果告诉给调用者,由调用者决定要如果处理结果,包括异常结果
  
  readFile('App.vue2',(err,result)=>{
  
  if(err) throw err;
  
  console.log(result)
  
  });
  
  //改进思路3
  
  //我们这样写是没问题了,但对于初学者来说可能有点不好理解,这里我们可以规定指定的函数来处理成功的结果和异常结果
  
  function readFile(fpath,succ,fail){
  
  fs.readFile(fpath,'utf-8',(err,data)=>{
  
  if(err) return fail(err);
  
  succ(data);
  
  })
  
  }
  
  readFile('App.vue',function (data) {
  
  console.log('succ');
  
  console.log(data);
  
  },function (err) {
  
  console.log(www.dfgjpt.com'fail');
  
  console.log(err);
  
  });
  
  假设有个需求,按顺序读取文件。那么我们可能会这样写
  
  readFile('1.txt'www.maituyul1.cn,function www.yongxin7.com(data) {
  
  console.log(data);
  
  readFile('2.js',www.cmeidi.cn function (data) {
  
  console.log(data);
  
  readFile('3.js'www.yongshiyule178.com,function (data) {
  
  console.log(data);
  
  });
  
  });
  
  });
  
  这就是一个典型的回调地狱问题,
  
  解决办法:使用ES6 的 Promise
  
  //1.Promise 是一个构造函数,既然是构造函数,那么我们就可以 new Promise()
  
  得到一个 Promise 实例
  
  //2.在Promise 上,有两个函数,分别叫 resolve(成功后的回调),和 reject(失败后的回调)
  
  3,在Promise 构造函数的 prototype 属性上,有个.then 方法,也就是说只要
  
  Promise 构造函数创建的实例,都可以访问到 .then() 方法
  
  4,Promise 表示一个异步操作,每当我们 new 一个 Promise 的实例,这个实例就表示一个
  
  具体的异步操作
  
  5,既然Promise 创建的实例,是一个异步操作,那么这个异步操作的结果,只有两种状态
  
  5.1 异步成功了
  
  5.2 异步失败了
  
  5.3 由于Promise 的实例,是一个异步操作,所以内部拿到操作的结果后,无法使用return
  
  把操作的结果返回给调用者,这时候,只能使用回调函数的形式,把成功或失败的结果返回
  
  给调用者
  
  每当new 一个 Promise 实例的时候,会立即执行这个异步操作中的代码
  
  注意:通过.then 指定回调函数的时候,成功的回调函数必须传。但是失败的函数的回调
  
  可以不传
  
  当第一个回调报错时,后面的异步操作都不执行了,当需要第一个异步操作不影响后续回调
  
  ,需要传入异常处理函数
  
  当后续的Promise 操作依赖于前面的Promise 操作的结果,那么可以使用catch 将异常抓住
  
  function readFile(www.michenggw.com fpath){
  
  var promise=new Promise(function (resolve,reject) {
  
  fs.readFile(fpath,'utf-8',(err,data)=>{
  
  if(err) return reject(www.thd178.com err);
  
  resolve(data);
  
  })
  
  });
  
  return promise;
  
  }
  
  var promise=readFile('Ap2p.vue');
  
  promise.then(function (data) {
  
  console.log('2111')
  
  console.log(data)
  
  return readFile('main.js')
  
  }).then(function (data) {
  
  console.log('222')
  
  return readFile(www.taoyang2vip.com'fs.js')
  
  }).then(function (data) {
  
  console.log('333')
  
  console.log(www.yongshi123.cn data)
  
  }).catch(function (www.mhylpt.com err) {
  
  console.log(www.jiuzhoyulpt.cn'err===============')
  
  console.log(err)
  
  });
  
  补充:console.dir() 可以显示一个对象所有的属性和方法。

猜你喜欢

转载自www.cnblogs.com/qwangxiao/p/10500521.html
今日推荐