Promise 是一个对象,是用来处理异步操作的,可以让异步调用的代码更加优雅、美观、有利于阅读。
node.js 采用异步回调的方式来处理需要等待的事件,使得代码会继续往下执行,不用在某个地方等待着。但是当有很多回调的时候,比如这个回调执行完需要去执行下个回调,然后接着再执行下个回调,这样就会造成回调层层嵌套,代码不清晰,很容易进入“回调地狱”,示例如下:
对3个文件进行读取操作
:
const fs = require('fs')
// 3个进程没有顺序,"异步"方式读取文件
// 由于电脑资源分配不均匀,以下3个进程执行前后顺序没有保障
fs.readFile('./files/01.txt','utf8',function(err,data){
if(err){
return console.log('文件错误了:'+err)}
console.log(data)
})
fs.readFile('./files/02.txt','utf8',function(err,data){
if(err){
return console.log('文件错误了:'+err)}
console.log(data)
})
fs.readFile('./files/03.txt','utf8',function(err,data){
if(err){
return console.log('文件错误了:'+err)}
console.log(data)
})
保障各个异步过程顺序执行(嵌套调用)
:
// 以下代码不好,嵌套调用层次深,形成回调地狱效果,代码不好维护
fs.readFile('./files/01.txt','utf8',function(err,data){
if(err){
return console.log('文件错误了:'+err)}
console.log(data)
fs.readFile('./files/02.txt','utf8',function(err,data){
if(err){
return console.log('文件错误了:'+err)}
console.log(data)
fs.readFile('./files/03.txt','utf8',function(err,data){
if(err){
return console.log('文件错误了:'+err)}
console.log(data)
})
})
})
es6新出的promise对象以及es7的async await 可以处理异步操作顺序执行。
相关异步操作
:
异步
:
在同一个时间中,可以发送多个进程进行执行。
同步
:
在同一个时间点,只有一个进程在执行。
Promise的三种状态
:
只有异步返回的结果可以改变其状态。所以,promise的过程一般只有两种:
pending->resolved
pending->rejected。
Promise的作用
:
promise对象有一个比较常用的then方法,用来执行回调函数,then方法接受两个参数,第一个是成功的resolved的回调,另一个是失败rejected的回调,第二个失败的回调参数可选。并且then方法里也可以返回promise对象,这样就可以链式调用了。
// 创建Promise对象
var p = new Promise(function(resolve,reject){
if(异步操作成功){
// resolve: 异步操作成功的回调函数
resolve(result)
}else{
// reject:异步操作失败的回调函数
reject(error)
}
})
// 对Promise对象结果进行处理
p
.then(
function(res){
// res 与 result一致,代表成功输出结果
}
)
.catch(
function(err){
// err 与 error一致,代表失败输出结果
}
)
对3个文件进行读取操作
:
// Promise介入(还没有顺序保障)
function getContent(filename){
var p = new Promise(function(){
// 异步操作
fs.readFile(filename,'utf8',function(err,data){
if(err){
return console.log('文件错误了:'+err)}
console.log(data)
})
})
}
getContent('./files/01.txt')
getContent('./files/02.txt')
getContent('./files/03.txt')
在Promise内部不要设置"业务逻辑"代码,同时内部把promise对象进行return返回:
function getContent(filename){
// resolve:代表异步成功执行的回调函数
// reject:代表异步失败执行的回调函数
return new Promise(function(resolve,reject){
// 异步操作
fs.readFile(filename,'utf8',function(err,data){
if(err){
return reject('文件错误了:'+err)}
resolve(data)
})
})
}
多个异步操作顺序执行、没有回调地狱:
getContent('./files/01.txt')
.then(function(rst){
console.log(rst)
// 返回一个实体Promise对象
// promise对象调用then完毕还会返回一个promise对象
// 因此可以继续调用then方法,默认情况promise对象是空的
// 如果在then内部return返回一个实体的Promise对象,则该then就把其返回了(就不是空的Promise对象了)
return getContent('./files/02.txt')
})
.then(function(rst){
console.log(rst)
return getContent('./files/03.txt')
})
.then(function(rst){
console.log(rst)
})
.catch(function(cuo){
// 统一接收以上各个异步进程的错误信息
console.log(cuo)
})
Promise对象,可以调用then、catch方法:
var p1 = getContent('./files/012323.txt')
console.log(p1) // Promise { }
// [Promise对象可以调用then和catch方法]接收 resolve 和 reject,进而获得相关的信息
p1
.then(function(rst){
console.log(rst)
})
.catch(function(cuo){
console.log(cuo)
})