promise 是es6引入的进行异步编程的新解决方案
旧的:旧方案是淡村的使用回调函数,如下面的各种情况
什么是异步编程:
- fs文件操作
- 数据库操作
- ajax数据请求
- 定时器
//1.Promise封装fs读取文件
let fs = require('fs');
//封装一个函数使用promise的方式读取文件
function mainfs(path){
return new Promise((resolve,reject)=>{
fs.readFile(path,(err,data)=>{
if(err) reject(err);
resolve(data)
})
});
}
mainfs('./text.txt').then(res=>{
console.log(res.toString(),'111');
}),res=>{
console.log(res,'222');
};
//2.Promise封装AJAX请求
function sendAJAX(url){
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open('GET',url)
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
resolve(xhr.response)
}else{
reject(xhr.status)
}
}
}
});
}
sendAJAX('https://api.imjad.cn/cloudmusic/?type=song&id=28012031').then(value=>{
console.log(value,'111');
},res=>{
console.log(res,'222');
});
promise 的优点:
- 支持链式调用可以解决回调地狱的问题,代码不断的向下递进(代码不已阅读,不便于异常处理).
- 指定回调函数的方式更加的灵活.(给promise对象绑定回调函数,甚至可以绑定多个函数)
Promise属性
1.PromiseStatus
Promise 状态的改变(PromiseStatus状态是Promise实例中的一个属性):
pending 可以变为resolve
pending 可以变为reject
有三种状态(pending,resolve,reject),但是只有两种转化过程(pending->resolve,peding->reject),
说明一个Promise最终只有两种改变状态,一个是pending到成功,一个pending到失败,
最终都会有一个结果,并且一个Promise的状态只可以改变一次,
2.PromiseResult
Promise 对象的值(PromiseResult保存的是异步任务的结果):
成功 resolve
失败 reject
Promise状态的改变的方式(有三种)
let p = new Promise((resolve,reject)=>{
//当前状态 pending
// resolve('ok') //1.pending(进行中) - fulfilled(成功)
// reject('error') //2.pending(进行中) - rejected(失败)
// throw '失败了' //3.pending(进行中) - rejected(失败)
})
console.log(p);
Promise 相关API
// 1 Promise构造函数 Promise(executor){}
(1)executor 执行器函数 (resolve,reject)=>{}
(1.1)resolve 定义内部成功执行的函数
(1.2)reject 定义内部失败执行的函数
执行器函数会在Promise 内部立即执行,异步操作在执行器中执行( Promise一旦创建立即执行 )
//2 Promise.prototype.then(onResolveed,onRejected)=>{};(Promise的实例对象)
(1)onResolveed:成功的回调
(2)onRejected:失败的回调
//3 Promise.prototype.catch(onRejected)=>{};
(1)onRejected:失败的回调
//举例
let p = new Promise((resolve,reject)=>{
// resolve('ok')
reject('error')
// throw '失败了'
})
// p.then(value=>{
// console.log(value);//ok
// },reason=>{
// console.log(reason);
// })
p.catch(res=>{
console.log(res);//error
})
//4 Promise.resolve(value)
(1)value:成功的数据或者是Promise对象;//说明:返回一个成功或者是失败的Promise对象
let p = Promise.resolve('ok11')
console.log(p);//Promise {<fulfilled>: 'ok11'}
注意:1.如果传递的参数为非Promise类型的对象,则返回的结果为成功的Promise 对象,参数的结果决定了Promise对象的resolve的结果
非Promise 类型的数据: string,number,boolean,undefined, null,[],{},
2.如果传入的参数是Promise对象, Promise 的结果有参数的结果决定
let p = Promise.resolve(new Promise((resolve,reject) => {
reject('error')
//reject('ok')
}))
console.log(p);//error / ok ,两种情况成功或者失败
//5 Promise.reject(value)
(1)任何数据或者是一个Promise对象;返回的结果一直是一个失败的Promise对象
let p = Promise.reject(123)
console.log(p);//Promise {<rejected>: '123'} //非Promise 类型的数据: string,number,boolean,undefined, null,[],{},
(2) 也可以是一个Promise对象,但是结果还是rejected的,result 是一个Promise类型的数据.
let p = Promise.reject(new Promise((resolve,reject) => {
resolve('ok')
}))
console.log(p);//Promise {<rejected>: Promise}
//6 Promise.all(value); value一般为一个Promise对象 组成的数组,返回的结果也是一个Promise对象.
返回的结果为Promise 数组都成功的值得数组,如果其中有一个失败了就返回这个失败的值
let p1 = Promise.resolve('1111')
let p2 = Promise.resolve('2222')
let p3 = Promise.resolve('3333')
let p4 = Promise.reject('4444')
let p = Promise.all([p1,p2,p3]);
console.log(p);//fulfilled->Array(3)
let _p = Promise.all([p1,p2,p4]);
console.log(_p);//rejected -> '4444'
//7 Promise.race(value);value一般为一个Promise对象 组成的数组,返回结果也是一个Promise对象.结果由第一个完成Promise状态改变的结果决定
let p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('1111')
},1000)
})
let p2 = Promise.resolve('2222')
let p3 = Promise.reject('3333')
let p = Promise.race([p1,p2]);
let _p = Promise.race([p1,p3]);
console.log(p); //fulfilled -> '2222'
console.log(_p);//rejected -> '3333'
一个Promise 指定多个成功(then)/失败(catch)回调函数,是否都会调用?
- 当Promise改变为对应状态时都会调用
//如果Promise函数状态没有改变那后面指定的回调(then)都不会执行
let p1 = new Promise((resolve,reject)=>{
// resolve('1111')
reject('error')
})
p1.then(value=>{
console.log(value);//1111
})
p1.then(value=>{
console.log(value);//1111
})
p1.then(value=>{
console.log(value);//1111
},reason=>{
console.log(reason);//error
})
改变Promise状态和指定回调函数谁先谁后?
1.都有可能
1.1如果promise内部是同步函数就是先改变状态后执行回调,
1.2如果promise内部是异步函数就是先执行回调在改变状态.
中断Promise链?
- 有且只有一种方式只有返回一个pending状态的Promise对象