一、什么是promise?
什么是promise呢?MDN上是这样解释的:Promise是一个对象,他代表了一个异步操作的最终完成或者失败。本质上Promise是一个函数返回的对象,我们可以在它上面绑定回调函数,这样我们就不需要一开始把回调函数作为参数传入这个函数了
实际上Promise与现实生活中的承诺非常相似。
在现实生活中呢,我们通常是这样理解Promise的:承诺(保证)某人会做某事或者某事的发生。也就是要给将来多要发生的事一
个承诺,但是谁都不能保证这件事一定会能够按照理想状态发生。
二、创建Promise
好了,下面我们来看一个如何创建promise.
Promise是浏览器自带的(但不是所有浏览器都支持promise)
有三种办法创建Promise实例(对象)
(1). 构造方法
let promise1 = new Promise((resolve,reject)=>{
resolve();
});
console.log(promise1);
(2).通过Promise实例的方法,Promise.then方法返回的也是一个promise对象
promise.then(onFulfilled, onRejected);
(3). 通过Promise的静态方法,Promise.resolve(),Promise.reject()
const promise2 = Promise.resolve();
promise3.then(function(value){
console.log(value);
});
从上面的代码可以看出,即便在业务逻辑上是层层嵌套,但是代码写法上,却十分优雅,也没有过多的嵌套。
三、 Promise 的作用
JavaScript可以用回调函数处理异步操作,原因就是Promise是一种强大的异步处理方式,而且它有统一的API和规范,Promise对象可以用同步的表现形式来书写异步代码(也就是说代码看起来是同步的,但本质上的运行过程是异步的)下面通过一个例子来看一下传统处理异步操作和Promise处理异步操作有哪些不同。
使用回调函数处理异步操作
var doSomething = function A(todo,callback){
setTimeout(function(){
console.log(todo);
callback();
},1000);
}
doSomething("起床",function(){
doSomething("刷牙",function(){
doSomething("吃早饭",function(){
console.log("上学");
});
});
});
//起床
//刷牙
//吃早饭
//上学
这样看起来代码非常冗余,并且读起来也很复杂,不利于后期维护
使用Promise处理异步操作
const myPromise = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('foo');
},1000);
});
myPromise
.then(
function(){
console.log("起床");
})
.then(
function(){
console.log("刷牙");
})
.then(
function(){
console.log("吃早饭");
})
.then(
function(){
console.log("上学");
})
//起床
//刷牙
//吃早饭
//上学
四、 Promise的三种状态
一个Promise 必然处于以下几种状态之一:
- 待处理(pending) :初始状态,既没有兑现 ,也没有被拒绝。
- 已兑现(fulfilled) :意味着操作成功完成。
- 已拒绝(rejected): 意味着操作失败。
PromiseState:就是promise的现在状态。
PromiseResult:就是resolve或者reject返回的结果
1、创建promise实例
//创建promise实例
let promise = new Promise((resolve,reject) => {
console.log(11);
});
console.log(promise);
当new Promise()(创建promise实例)执行之后,Promise对象的状态会被初始化为pending
2、当你调用resolve时,状态立马变成了fulfilled(成功状态)
let promise = new Promise((resolve,reject) => {
resolve();
console.log(11);
});
console.log(promise);
3、当调用reject时,状态就变成了rejected(失败状态)
4、如果两个状态都存在,那么谁先调用谁为准
5、PromiseResult为resolve或者reject返回的结果
function clg(){
return '我就是返回的结果'
}
let promise = new Promise((resolve,reject) => {
resolve(clg());
});
console.log(promise);
// Promise {<fulfilled>: '我就是返回的结果'}
// [[Prototype]]: Promise
// [[PromiseState]]: "fulfilled"
// [[PromiseResult]]: "我就是返回的结果"
五、Promise的实例方法
new Promise是同步的
通过上面的打印我们可以看到Promise.prototype上有以下几种实例方法,下满我们来研究一下这些方法都有什么作用,并且如何使用
1、Promise.prototype.then()
MDN上这样解释:then( ) 方法返回一个Promise。它最多需要有两个参数:promise的成功和失败情况的回调函数。
resolve或者reject返回的结果实际上是返回给then的,then函数里的参数是两个异步回调函数,第一个参数接收esolve返回的数据,第二个函数参数接收reject返回的数据
1.1、接收resolve返回的数据
const promise1 = new Promise((resolve,reject) =>{
resolve('Success!');
});
promise1.then((value) => {
console.log(value);
});
1.2、接收reject返回的数据
const p = new Promise((resolve,reject) =>{
// resolve('Success!');
reject('failed!');
});
p.then(
(value) => {
console.log(value);
},
(err) => {
console.log(err);
}
);
console.log(p);
1.3、缺失某个状态或参数非函数
在then()方法中,如果忽略了某一个状态的回调函数,或者填写一个其他不是函数的参数,那么then方法将不会返回缺失该状态的回调函数信息,但是并不会产生错误
此时状态也变为pending(待定状态)。
返回值
下面我们来看两个例子
1、不添加return
2、添加return
很明显我们能够看到二者的差别
- 返回了一个值,那么then返回的Promise将会变为成功状态,并且将返回的值,作为成功状态的回调函数的参数值
- 没有返回值,那么then方法返回的Promise因为变为成功状态,但是该成功状态的回调函数的参数值为underfined。
- 同时new Promise 是同步的。promise如果没有使用resolve或reject更改状态时,状态为pending,当完成异步任务之后,状态分为成功或失败,此时我们就可以用resolve()和reject(),同时状态做出相应的改变
六、Promise封装异步任务
传统写法
// 定义一个异步的延迟函数:异步函数结束1秒之后,再执行cb回调函数
function fun1(cb) {
setTimeout(function () {
console.log('即将执行cb回调函数');
cb();
}, 1000);
}
// 先执行异步函数 fun1,再执行回调函数 myCallback
fun1(myCallback);
// 定义回调函数
function myCallback() {
console.log('我是延迟执行的cb回调函数');
}
传统写法的化简版
function fun1(cb){
setTimeout(cb,1000);
}
fun1(function () {
console.log('我是延迟执行的cb回调函数');
})
Promise写法
function myPromise() {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 1000);
});
}
// 先执行异步函数 myPromise,再执行回调函数
myPromise().then(() => {
console.log('我是延迟执行的回调函数');
});