比如我们现在有个读取文件的需求,那么用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是异步的,主线程在遇到异步函数时,会将异步任务放到队列中,然后//继续执行,所以这里得到undefinedconsole.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('fail'); console.log(err);});
假设有个需求,按顺序读取文件。那么我们可能会这样写
readFile('1.txt',function (data) { console.log(data); readFile('2.js',function (data) { console.log(data); readFile('3.js',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 将异常抓住也就是说,当前面任意一个Promise 执行出错,都会被catch 抓住function readFile(fpath){ var promise=new Promise(function (resolve,reject) { fs.readFile(fpath,'utf-8',(err,data)=>{ if(err) return reject(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('fs.js')}).then(function (data) { console.log('333') console.log(data)}).catch(function (err) { console.log('err===============') console.log(err)});
补充:console.dir() 可以显示一个对象所有的属性和方法。