promise
异步编程
fs文件操作
fs.readFile('./index.js',(err,data)=>{})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.btn{
background-color: blue;
color: aliceblue;
}
</style>
</head>
<body>
<h1>Promise初体验</h1>
<hr>
<button class="btn">点击抽奖</button>
<script>
//生成随机数
function rand(m,n){
return Math.ceil(Math.random()*(n-m+1))+m-1;
}
const btn=document.querySelector('.btn')
btn.addEventListener('click',function(){
/* setTimeout(()=>{
let n=rand(1,100)
if(n<=30)return console.log("恭喜中奖,奖金为10w");
else{return console.log("未中奖,再接再厉");}
},2000) */
const p=new Promise((resolve,reject)=>{
setTimeout(()=>{
let n=rand(1,100)
if(n<=30)
{resolve(n)}
else
{reject(n)}
},200)
})
p.then((r1)=>{console.log("恭喜中奖,奖金为10w,你的中奖数字为"+r1)},(err)=>{console.log("未中奖,再接再厉"+err)})
})
</script>
</body>
</html>
数据库操作
AJAX
$.get('/server',()=>{})
定时器
setTimeout(()=>{},2000)
1.promise是异步操作的新解决方案,注:旧方案是回调函数
2.具体表达:
1)promise从语法上来看是一个构造函数
2)promise对象用来封装一个异步操作并可以获取其成功或失败得结果值
指定回调函数的方式更加灵活
promise:启动异步任务=>返回promise对象=>给promise对象绑定回调函数(甚至可以在异步任务结束后指定多个)
3.promise支持链式调用,可以解决回调地狱的问题
4.promise的状态改变
1)pending变为resolved
2)pendin变为rejected
说明:只有2种状态,且一个promise对象只能改变一次,无论变为成功还是失败,都会有一个结果数据,成功的结果数据一般称为value,失败的结果数据一般称为reason
##Promise的状态
实例对象的一个属性[PromiseState]
*pending 未决定的
*resolved/fullfilled 成功
*rejected 失败
##Promise对象的值
实例对象中的另一个属性[PromiseResult]
保存着对象的[成功/失败]的结果
*resolve
*reject
##promise的构造函数:promise(excutor){}
executor函数:执行器(resolve,reject)=>{}
executor会在promise内部立即同步执行,异步操作在执行器执行
##promise.prototype.then方法:(onResolved,onRejected)=>{}
指定用于得到成功的value的回调和用于得到失败的reason的失败回调返回一个新的promise对象
##promise.prototype.catch方法:(onRejected)=>{}
获取失败的回调对象(reason)=>{}
##promise.resolve方法:(value)=>{}
有时需要将现有对象转为 Promise 对象,Promise.resolve()
方法就起到这个作用。
value成功的数据或promise对象
如果传入的参数为非promise类型的对象,则结果为成功的promise对象
返回一个成功/失败的promise对象
(1)如果传入的参数为promise类型的对象,Promise.resolve
将不做任何修改、原封不动地返回这个实例。
(2)参数是一个thenable
对象
thenable
对象指的是具有then
方法的对象
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
});
(3)参数不是具有then
方法的对象,或根本就不是对象
如果参数是一个原始值,或者是一个不具有then
方法的对象,则Promise.resolve
方法返回一个新的 Promise 对象,状态为resolved
。
const p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
4)不带有任何参数
Promise.resolve()
方法允许调用时不带参数,直接返回一个resolved
状态的 Promise 对象。
所以,如果希望得到一个 Promise 对象,比较方便的方法就是直接调用Promise.resolve()
方法。
const p = Promise.resolve();
p.then(function () {
// ...
});
需要注意的是,立即resolve()
的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时。
##promise.reject方法:(reason)=>{}
Promise.reject(reason)
方法也会返回一个新的 Promise 实例,该实例的状态为rejected
。
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s)
});
// 出错了
注意,Promise.reject()
方法的参数,会原封不动地作为reject
的理由,变成后续方法的参数。这一点与Promise.resolve
方法不一致。
const thenable = {
then(resolve, reject) {
reject('出错了');
}
};
Promise.reject(thenable)
.catch(e => {
console.log(e === thenable)
})
// true
reason:失败的原因
返回一个失败的promise对象
##promise.all方法(promise)={}
promises:包含n个promise的数组
返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败就直接失败
import fs from 'then-fs'
const promiseArr=[
fs.readFile('../files/1.txt','utf-8'),
fs.readFile('../files/2.txt','utf-8'),
fs.readFile('../files/3.txt','utf-8')
]
Promise.all(promiseArr)
.then((result)=>{
console.log(result);
}).catch(err=>{console.log(err.message);})//[ '111', '222', '333' ]
##promise.race 方法(promise)=>{}
promises:包含n个promise的数组
返回一个新的promise,第一个完成的promise的结果对象就是最终的结果对象
import fs from 'then-fs'
const promiseArr=[
fs.readFile('../files/1.txt','utf-8'),
fs.readFile('../files/2.txt','utf-8'),
fs.readFile('../files/3.txt','utf-8')
]
Promise.race(promiseArr)
.then((result)=>{
console.log(result);
}).catch(err=>{console.log(err.message);})//111
改变promise的状态
(1)resolve(value)pending变为resolved
(2)reject(reason)pending变为rejected
(3)抛出异常,pending变为rejected
一个promise指定多个成功/失败的回调函数,当promise改变为对应状态时都会调用
正常情况是先指定回调在改变状态,但可以反过来
1.先改变状态再指定回调
1)在执行器直接调用resolve()/reject()
2) 延迟更长时间才调用then(
2.得到数据
1)如果先指定回调,当状态改变时,回调函数就会被调用,得到数据
2)如果先改变状态,当指定回调时,回调就会调用,得到数据
中断promise链
(1)当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
(2)在回调函数中返回一个pending状态的Promise对象
const p=new Promise((resolve,reject)=>{
setTimeout(()=>{resolve('ok')},100)
})
p.then((value)=>{console.log(value);
return new promise=(()=>{})})
.then(value=>{console.log(value);})
.then(value=>{console.log(value);})
async
1.如果返回值是一个非promise对象的数据,则返回数据本身
2.如果返回的是一个promise对象,则promise对象是什么则返回什么
3.抛出异常,返回的值是一个失败的promise对象
await
1.await右侧的表达式一般为promise对象,但也可以其他的值
2.如果表达式是promise对象,await返回的是promise成功的值
3.如果表达式是其他的值,直接将此值作为await的返回值
import fs from 'then-fs'
async function getFile(){
const r1=await fs.readFile('../files/1.txt','utf8')
console.log(r1);
const r2=await fs.readFile('../files/2.txt','utf8')
console.log(r2);
const r3=await fs.readFile('../files/3.txt','utf8')
console.log(r3);
}
getFile()