💡 前端异步编程经历了 callback、promise、generator、async/await 几个阶段。
💡 目前在简单场景使用 callback,复杂场景使用 promise 和 async/await,由于generate 的api不易理解并且不易于使用,所以很少使用。
Promise 的含义
Promise 是异步编程的一种解决方案,比传统的回调函数和事件更合理更强大,解决了回调地狱的问题。
从语法上说,Promise 是一个对象,从它可以获取异步操作的信息。
Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
状态特性
让使用 promise 的用户可以及时通知 promise 任务执行结果。
then特性
让使用 promise 的用户可以控制 执行完一个任务后执行下一个任务。
使用回调进行异步编程的话,都是用户手动控制的,使用promise的话,只需要告诉promise:“我要执行什么任务”、“我执行的任务结束了”、“然后我要做什么”。
Promise 对象的两个特点:
对象的状态不受外界影响
。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Fulfilled(已成功)、Rejected(已失败)。一旦状态改变就不会再变
,任何时候都可以得到这个结果。状态改变只有两种可能:从pending到Fulfilled 和 从Pending到Rejected.
Promise 的缺点:
无法取消Promise
。一旦新建就会立即执行,无法中途取消。- 如果不设置回调函数,
Promise 内部抛出的错误不会反应到外部
当处于Pending状态时,无法得知目前进展到哪一个阶段
(刚开始或即将完成)。
基本用法
ES6 规定,Promise 对象是一个构造函数,用来生成 Promise 实例。
const promise = new Promise(function (resolve, reject) {
// ...some code
if (异步操作成功)
resolve(value)
else
reject(error)
});
Promise 函数接受一个函数作为参数,该函数有两个参数:resolve和reject
。
resolve 函数的作用是,将状态从 Pending变成Resolved,操作成功时调用。reject函数是,将状态变成 rejected,失败时调用。
then 方法可以接受两个回调函数作为参数。第一个是状态变成Resolved时调用,第二个是变成rejected时调用。其中第二个参数是可选的。这两个函数都接受promise对象传出的值作为参数【下方then方法中有具体说明】。
Promise新建后回立即执行
。然后,then 方法指定的回调函数将在当前脚本所有同步任务执行完成后才会执行。
// 使用Promise 包装一个图片加载的异步操作
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
var image = new Image();
image.onload = function() {
resolve(image)
}
image.onerror = function() {
reject(new Error(`could not load image at ${
url}`))
}
image.src = url;
})
}
// 由于抛出错误,promise状态已经改变为rejected,再调用resolve将不会改变promise状态
const p = new Promise((resolve, reject) => {
throw new Error('test-error');
resolve('test');
});
p.then(
data => console.log(1, 'resolve', data),
data => console.log(1, 'reject', data)
);
// 执行结果 1 "reject" Error: test-error
// 增加一道代码,面试题:如果图片加载不出来,用另一个替代
function loadImageAsync(url) {
var image = new Image();
return new Promise(function(resolve, reject) {
image.src = url;
document.body.appendChild(image)
image.onload = function() {
resolve('load img success')
}
image.onerror = function() {
img.src = '替换的路径'
reject('load img error')
}
})
}
loadImageAsync('图片地址').then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
promise对象的方法:then、catch、all、race
-
Promise.prototype.then() 为Promise实例添加状态改变时的回调函数
then方法接受两个参数,onFulfilled(状态变为fullfilled的回调)和onRejected(状态变为rejected的回调)。
返回一个新的promise对象,返回的 promise对象的状态与 then的参数(onFulfilled、onRejected)和onFulfilled、onRejected方法中返回的值有关。
-
1、then 方法不传参数
如果不传参数,则 then方法返回的promise 和 调用then的promise的状态 一致。
更具体地,如果 没有onFullfilled参数 并且promise的状态为fullfilled,那么 then方法返回的promise 和 调用then方法的promise状态 一致;
如果 没有onRejected参数 并且promise状态为rejected,那么then方法返回的promise 和调用then方法的promise状态 一致。可以简单地理解:如果上一个promise不处理,那就下一个promise处理。
var p = new Promise(resolve => { throw new Error('test'); }); p.then( ()
-