promise一脸懵逼...
// 要求:封装一个方法,能根据路径读取文件,并把内容返回
const fs=require('fs')
const path=require('path')
1. 普通读取文件的方式
1 const fs=require('fs') 2 const path=require('path') 3 4 /* 5 fs.readFile(path.join(__dirname,'./files/1.txt'),'utf-8',(err,dataStr)=>{ 6 if(err) throw err 7 console.log(dataStr) 8 }) 9 */
命令行敲 :node .\01.封装读取文件的方法.js,结果为1.txt的内容 :111
2.调用function
1 function getFileByPath(fpath){ 2 fs.readFile(fpath,'utf-8',(err,dataStr)=>{ 3 if(err) throw err 4 console.log(dataStr) // 打印->111 5 }) 6 } 7 // getFileByPath(path.join(__dirname,'./files/1.txt')) // 结果 ->111 8 // var result=getFileByPath(path.join(__dirname,'./files/1.txt')) 9 // console.log(result) // 结果 ->undefined
3.加入回调函数
1 function getFileByPath(fpath,callback){ 2 fs.readFile(fpath,'utf-8',(err,dataStr)=>{ //异步 3 if(err) throw err 4 5 callback(dataStr) 6 }) 7 } 8 getFileByPath(path.join(__dirname,'./files/1.txt'),(dataStr)=>{ 9 console.log(dataStr+'-----') 10 //结果: 111----- 11 })
4.对回调函数进行修改
1 callback中有两个参数,一:失败的结果 二:成功的结果 2 规定:如果成功后,返回的结果,应该位于callback参数的第二个位置, 3 此时第一个参数没有出错,所以第一个放一个null 4 如果失败了,第一个位置放err对象,第二个位置放undefined 5 6 function getFileByPath(fpath,callback){ 7 fs.readFile(fpath,'utf-8',(err,dataStr)=>{ 8 if(err) callback(err) 9 10 callback(null,dataStr) 11 }) 12 } 13 //读一个不存在的文件,验证err 14 getFileByPath(path.join(__dirname,'./files/11.txt'),(err,dataStr)=>{ 15 //失败 16 if(err) return console.log(err.message) 17 //成功 18 console.log(dataStr) 19 })
5.提高版
1 function getFileByPath(fpath,succCb,errCb){ 2 fs.readFile(fpath,'utf-8',(err,dataStr)=>{ 3 if(err) return errCb(err) 4 5 succCb(dataStr) 6 }) 7 } 8 getFileByPath(path.join(__dirname,'./files/1.txt'),function(data){ 9 console.log(data+"成功了") 10 },function(err){ 11 console.log("失败的结果,使用失败的回调处理"+err.message) 12 })
6.需求:先读取文件1,再读取文件2,再读取文件3
1 function getFileByPath(fpath,succCb,errCb){ 2 fs.readFile(fpath,'utf-8',(err,dataStr)=>{ 3 if(err) return errCb(err) 4 5 succCb(dataStr) 6 }) 7 } 8 9 // 需求:先读取文件1,再2再3 10 getFileByPath(path.join(__dirname,'./files/1.txt'),function(data){ 11 console.log(data) 12 13 getFileByPath(path.join(__dirname,'./files/2.txt'),function(data){ 14 console.log(data) 15 16 getFileByPath(path.join(__dirname,'./files/3.txt'),function(data){ 17 console.log(data) 18 }) 19 }) 20 })
1.Primise
1 // 1.Promise是一个构造函数 2 // 2,在Promise上,有两个函数:resolve(成功之后的回调函数)和reject(失败之后的回调函数) 3 // 3.在Promise 构造函数的 Prototype 属性上,有一个 .them()方法,,即只要是Promise构造函数创建的实例,都可以访问到 .then()方法 4 // 4.如果Promise表示一个异步操作,每次new一个promise实例时,此实例表示一个具体的异步操作 5 // 5.Promise创建的实例是异步操作,那么这个异步操作的结果,只能有两种状态: 6 // 5.1状态1:异步执行成功,在内部调用成功的回调函数 - resolve 把结果返回给调用者 7 // 5.2状态2:异步执行失败,在内部调用失败的回调函数 - reject 把结果返回给调用者 8 // 5.3由于promise的实例是异步操作,所有内部拿到操作的结果后,无法使用return 把操作的结果返回给调用者, 9 // 只能使用回调函数的形式,将成功或失败的结果返回给调用者 10 11 // 每当new一个Promise实例的时候,就会立即执行异步操作中的代码, 12 // 即,new的时候,除了能得到一个promise实例外,还会调用为promise构造函数传递的那个function,执行此function中的异步操作代码
1 const fs=require('fs') 2 /*var promise=new Promise(function(){ 3 fs.readFile('./files/2.txt','utf-8',(err,dataStr)=>{ 4 if(err) throw err 5 console.log(dataStr) 6 }) 7 }) 8 */
1 /*function getFileByPath(fpath){ 2 var promise=new Promise(function(){ 3 fs.readFile(fpath,'utf-8',(err,dataStr)=>{ 4 if(err) throw err 5 console.log(dataStr) 6 }) 7 }) 8 } 9 getFileByPath('./files/2.txt') 10 */
1 function getFileByPath(fpath){ 2 var promise=new Promise(function(resolve,reject){ 3 fs.readFile(fpath,'utf-8',(err,dataStr)=>{ 4 if(err) return reject(err) 5 resolve(dataStr) 6 }) 7 }) 8 return promise 9 } 10 var p=getFileByPath('./files/2.txt') 11 p.then(function(data){ 12 console.log(data+'------') 13 },function(err){ 14 console.log(err+'------') 15 })
改进:
1 function getFileByPath(fpath){ 2 return new Promise(function(resolve,reject){ 3 fs.readFile(fpath,'utf-8',(err,dataStr)=>{ 4 if(err) return reject(err) 5 resolve(dataStr) 6 }) 7 }) 8 } 9 getFileByPath('./files/2.txt') 10 .then(function(data){ 11 console.log(data+'------') 12 },function(err){ 13 console.log(err+'------') 14 })
解决回调地狱:在上一个 .then 中,返回一个新的promise实例,可以继续使用下一个.then来处理
1 const fs=require('fs') 2 3 function getFileByPath(fpath){ 4 return new Promise(function(resolve,reject){ 5 fs.readFile(fpath,'utf-8',(err,dataStr)=>{ 6 if(err) return reject(err) 7 resolve(dataStr) 8 }) 9 }) 10 } 11 // 先读取1,后2 再3 12 // 注意:通过.then指定 回调函数的时候,成功的回调函数,必须传,失败的回调,可以省略不传 13 getFileByPath('./files/1.txt') 14 .then(function(data){ 15 console.log(data) 16 17 return getFileByPath('./files/2.txt') 18 }) 19 .then(function(data){ 20 console.log(data) 21 22 return getFileByPath('./files/3.txt') 23 }) 24 .then(function(data){ 25 console.log(data) 26 })
在.then中指定失败的操作:
1 // 如果前面的promise执行失败,不想让后续的Promise被终止,可以为每个promise指定失败的操作 2 getFileByPath('./files/11.txt') 3 .then(function(data){ 4 console.log(data) 5 6 return getFileByPath('./files/2.txt') 7 },function(err){ 8 console.log('1失败了,2继续'+err.message) 9 // 返回新的promise 10 return getFileByPath('./files/2.txt') 11 }) 12 .then(function(data){ 13 console.log(data) 14 15 return getFileByPath('./files/3.txt') 16 }) 17 .then(function(data){ 18 console.log(data) 19 }) 20 21 console.log('为什么会执行我?') 22 23 PS D:\webstorm\01\promise> node .\04.使用promise解决回调地狱.js 24 为什么会执行我? 25 1失败了,2继续ENOENT: no such file or directory, open 'D:\webstorm\01\promise\files\11.txt' 26 222 27 333
有依赖关系时,异常捕获:
1 / 有时候,需求:与上面的需求刚好相反,如果后续的promise执行,依赖于前面promise执行的结果, 2 // 如果前面失败了,则后面的就没有继续执行下去的意义 3 getFileByPath('./files/1.txt') 4 .then(function(data){ 5 console.log(data) 6 7 return getFileByPath('./files/21.txt') 8 }) 9 .then(function(data){ 10 console.log(data) 11 12 return getFileByPath('./files/3.txt') 13 }) 14 .then(function(data){ 15 console.log(data) 16 }).catch(function(err){ //如果前面有任何的promise执行失败,则立即终止所有的promise操作,进入catch中 17 console.log('自己处理的错误的捕获:'+err.message) 18 })
JQuery中ajax使用promise指定成功回调函数:
1 <input type="button" value="获取数据" id="btn"> 2 3 <script src="./node_modules/jquery/dist/jquery.min.js"></script> 4 5 <script> 6 $(function(){ 7 $('#btn').on('click',function(){ 8 $.ajax({ 9 url:'./data.json', 10 type:'get', 11 dataType:'json', 12 // success(data){ 13 // console.log(data) 14 // } 15 }) 16 .then(function(data){ 17 console.log(data) 18 }) 19 }) 20 })