Promise 是什么?
- 抽象表达:
- Promise 是一门新的技术(ES6 规范)
- Promise 是 JS 中进行异步编程的新解决方案
备注:旧方案是单纯使用回调函数
- 具体表达:
- 从语法上来说: Promise 是一个构造函数
- 从功能上来说: promise 对象用来封装一个异步操作并可以获取其成功/失败的结果值
promise 的状态改变
- pending 变为 resolved/fullfilled
- pending 变为 rejected
说明: 只有这 2 种, 且一个 promise 对象只能改变一次,无论变为成功还是失败, 都会有一个结果数据,成功的结果数据一般称为 value, 失败的结果数据一般称为 reason
promise 的基本流程

promise 的基本使用
const btn = document.querySelector('#btn');
//绑定单击事件
btn.addEventListener('click', function(){
//Promise 形式实现
// resolve 解决 函数类型的数据
// reject 拒绝 函数类型的数据
const p = new Promise((resolve, reject) => {
setTimeout(() => {
//30% 1-100 1 2 30
//获取从1 - 100的一个随机数
let n = rand(1, 100);
//判断
if(n <= 30){
resolve(n); // 将 promise 对象的状态设置为 『成功』
}else{
reject(n); // 将 promise 对象的状态设置为 『失败』
}
}, 1000);
});
//调用 then 方法
// value 值
// reason 理由
p.then((value) => {
alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券, 您的中奖数字为 ' + value);
}, (reason) => {
alert('再接再厉, 您的号码为 ' + reason);
});
});
如何使用 Promise
- Promise 构造函数: Promise (excutor) {}
- executor 函数: 执行器 (resolve, reject) => {}
- resolve 函数: 内部定义成功时我们调用的函数 value => {}
- reject 函数: 内部定义失败时我们调用的函数 reason => {}
说明: executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行
let p = new Promise((resolve, reject) => {
console.log(111);
});
console.log(222); // 111 222
-
Promise.prototype.then 方法: (onResolved, onRejected) => {}
-
onResolved 函数: 成功的回调函数 (value) => {}
-
onRejected 函数: 失败的回调函数 (reason) => {}
说明: 指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调,返回一个新的 promise 对象
let p = new Promise((resolve, reject) => {
// resolve(111);
reject(222)
});
p.then((value) => {
console.log(value) // 111
},(reason) => {
console.log(reason) // 222
})
- Promise.prototype.catch 方法: (onRejected) => {}
- onRejected 函数: 失败的回调函数 (reason) => {}
说明: then()的语法糖, 相当于: then(undefined, onRejected)
let p = new Promise((resolve, reject) => {
reject(222)
});
p.catch((reason)=>{
console.log(reason) // 222
})
-
Promise.resolve 方法: (value) => {}
- value: 成功的数据或 promise 对象,说明: 返回一个成功/失败的 promise 对象
//如果传入的参数为 非Promise类型的对象, 则返回的结果为成功promise对象
let p1 = Promise.resolve(521);
p1.then((res) => {
console.log(res) // 521
})
//如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果
let p2 = Promise.resolve(new Promise((resolve, reject) => {
resolve('OK');
}));
console.log(p2);
p2.then(reason => {
console.log(reason); // OK
})
- Promise.reject 方法: (reason) => {}
- reason: 失败的原因,说明: 返回一个失败的 promise 对象
let p = Promise.reject(521);
console.log(p) // Promise {<rejected>: 521}
let p3 = Promise.reject(new Promise((resolve, reject) => {
resolve('OK');
}));
console.log(p3);

-
Promise.all 方法: (promises) => {}
- promises: 包含 n 个 promise 的数组
说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就直接失败
let p1 = new Promise((resolve, reject) => {
resolve('OK');
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.all([p1, p2, p3]);
console.log(result);

let p1 = new Promise((resolve, reject) => {
resolve('OK');
})
let p2 = Promise.reject('Error');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.all([p1, p2, p3]);
console.log(result);

- Promise.race 方法: (promises) => {}
- promises: 包含 n 个 promise 的数组
说明: 返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
//调用
const result = Promise.race([p1, p2, p3]);
console.log(result);

promise 的几个关键问题
- 如何改变 promise 的状态?
- resolve(value): 如果当前是 pending 就会变为 resolved
- reject(reason): 如果当前是 pending 就会变为 rejected
- 抛出异常: 如果当前是 pending 就会变为 rejected
let p = new Promise((resolve, reject) => {
//1. resolve 函数
// resolve('ok'); // pending => fulfilled (resolved)
//2. reject 函数
// reject("error");// pending => rejected
//3. 抛出错误
// throw '出问题了';
});
-
一个 promise 指定多个成功/失败回调函数, 都会调用吗?
当 promise 改变为对应状态时都会调用
let p = new Promise((resolve, reject) => {
resolve('OK');
});
///指定回调 - 1
p.then(value => {
console.log(value);
});
//指定回调 - 2
p.then(value => {
alert(value);
});
-
改变 promise 状态和指定回调函数谁先谁后?
- 都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
- 如何先改状态再指定回调?
① 在执行器中直接调用 resolve()/reject()
② 延迟更长时间才调用 then()
- 什么时候才能得到数据?
① 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
② 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
-
promise.then()返回的新 promise 的结果状态由什么决定?
- 简单表达: 由 then()指定的回调函数执行的结果决定
- 详细表达:
① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果\
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
// console.log(value);
//1. 抛出错误
// throw '出了问题';
//2. 返回结果是非 Promise 类型的对象
// return 521;
//3. 返回结果是 Promise 对象
// return new Promise((resolve, reject) => {
// // resolve('success');
// reject('error');
// });
}, reason => {
console.warn(reason);
});
console.log(result);
- promise 如何串连多个操作任务?
- promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
- 通过 then 的链式调用串连多个同步/异步任务
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
return new Promise((resolve, reject) => {
resolve("success");
});
}).then(value => {
console.log(value); // success
}).then(value => {
console.log(value); // undefined
})
-
promise 异常传透?
- 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调,
- 前面任何操作出了异常, 都会传到最后失败的回调中处理
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
throw '失败啦!';
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason); // 失败啦
});
- 中断 promise 链?
- 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
- 办法: 在回调函数中返回一个 pendding 状态的 promise 对象
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
console.log(111);
//有且只有一个方式
return new Promise(() => {});
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});
async 函数
- 函数的返回值是 promise 对象
- promise 对象的结果是由 async 函数执行的返回值决定。
- 如果返回值是一个非 Promise 类型的数据,则结果是一个成功的 Promise
async function fun() {
return 111
}
let result = fun()
console.log(result) // Promise {<fulfilled>: 111}
- 如果返回值是一个 Promise 类型的数据,则结果由返回的 Promise 决定
async function fun() {
return new Promise((resolve) => {resolve(123)})
}
let result = fun()
console.log(result)

async function fun() {
return new Promise((resolve,reject) => {reject(123)})
}
let result = fun()
console.log(result)

async function fun() {
throw '123'
}
let result = fun()
console.log(result)

await 表达式
- await 右侧的表达式一般为 promise 对象,但也可以是其他值
- 如果表达式是 promise 对象,await 返回的是 promise 成功的值
- 如果表达式是其他值,直接将此值作为 await 的返回值
- 如果 awiat 的 promise 失败了,就会抛出异常,要通过 try...catch..捕获处理
async function fun(){
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
}, 1000)
})
let result = await p
console.log(result)
}
fun() // 1秒后打印 111
async/await 结合
案例: 想要读取三个文件的内容,并组合在一起


这种写法好处是没有回调函数了。