这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战前端
复习Promise知识,关于它的概念,使用方式等,还有注意事项。 参考依然是阮一峰老师的 ESCMAScript6入门 es6.ruanyifeng.com/ ,写它的缘由是在项目中能常常的使用到Promise作异步处理,,但对它并无系统性的了解。vue
简单说下,Promise是一种js单线程的异步处理方案,在对后端的接口请求中咱们常常会用到,相信大多数前端都对这个不陌生。ES6将Promise进行来便准规范。es6
promise有三种状态,而且具有了状态不受干扰以及状态一旦改变就不会再变的特性。正则表达式
三种状态分别是mongodb
须要注意的是,一旦执行,中途就没法取消,若是不设置回调函数,Promise内部会抛出错误,并且在pending状态中,不知道会进展到哪一个阶段。后端
在前端的使用过程当中,通常在请求的时候都会用到,有的用来封装请求,也有在store中使用,固然也是封装请求的。大体以下api
function getUserInfo(data) {
return new Promise((resolve, reject) => {
// 接口的方法
if(true) {
resolve('返回参数')
} else {
reject('错误的信息')
}
})
}
getUserInfo(data).then(res => {
console.log(res)
}).catch(res => {
console.log(res)
})
复制代码
这个应该是最多见的使用方式,还有就是Promise.all()的方式,会在后边写到。数组
下边一个异步加载图片的例子promise
function loadImageAsync(url) {
return new Promise((resolve, reject) => {
const image = new Image()
image.onload = function() {
resolve(image)
}
image.onerror = function() {
reject(new Error('Could not load image at '+ url))
}
image.src = url
})
}
复制代码
这里比较重要的一点仍是promise的已成功 和已失败两个回调,在获得图片路径的时候,使用resolve来返回正确的地址,错误的时候返回错误的地址。markdown
在promise中,通常是从进行中到已成功或已失败。在这个过程当中是有回调地址的,若是当前回调地址为一个新的promise,那么当前这个promise的状态实际上是取决于当前回调这个promise的状态的。
例如:
const p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('p1'), 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => resolve(p1), 1000)
})
p2.then(result => console.log(result,'result')) // p1 result
.catch(error => console.log(error,'error'))
复制代码
当前这个例子彷佛是看不出来的,p2是成功回调,p1也是成功回调。对比第二个例子就能清晰看出来了
const p1 = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('错了')), 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => resolve(p1), 1000)
})
p2.then(result => console.log(result,'result'))
.catch(error => console.log(error,'error')) // Error: 错了
复制代码
两个比较,咱们就能够清晰认识到这一点。
Promise 实例具备then方法,then方法是定义在原型对象Promise.prototype上的。then方法能够链式调用,通俗说就是葫芦娃救爷爷,一个接一个。
一样,promise.prototype上还有catch,上一个是处理回调的,这个是用来处理错误的。
两种等价的写法
// 写法一
const promise = new Promise(function(resolve, reject) {
try {
throw new Error('test');
} catch(e) {
reject(e);
}
});
promise.catch(function(error) {
console.log(error);
});
// 写法二
const promise = new Promise(function(resolve, reject) {
reject(new Error('test'));
});
promise.catch(function(error) {
console.log(error);
});
// 比较上面两种写法,能够发现reject()方法的做用,等同于抛出错误。
复制代码
并且Promise 对象的错误会一直向后传递,直到被捕获
finally()
方法用于指定无论 Promise 对象最后状态如何,都会执行的操做。该方法是 ES2018 引入标准的。相对用的比较少,在特定环境下,finally 也会有奇效,具体看业务场景。
Promise.all()
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
这个方法,在nuxtjs作服务端渲染的时候会用的比较多一些。用的方式也很特别。打包一块儿搞,所有返回后才走then方法。 状态有两种:所有为fulfilled,状态就是fuifilled;若是有一个是rejected,那么状态就为rejected.
所有为fulfilled
const p1 = new Promise((resolve, reject) => {
resolve('p1');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
resolve('p2');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result,'then')) // ["p1", "p2"] "then"
.catch(e => console.log(e,'catch'));
复制代码
有一个是rejected
const p1 = new Promise((resolve, reject) => {
resolve('p1');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result,'then'))
.catch(e => console.log(e,'catch'));
复制代码
再看下面的例子
const p1 = new Promise((resolve, reject) => {
resolve('p1');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result,'then'))
.catch(e => console.log(e,'catch'));
复制代码
这个彷佛咱们以前所说的不一致,主要是由于p2中使用了catch, p2首先进入rejected,可是由于有本身的catch方法,方法会返回一个新的实例,p2指向的实际是这个实例。实例执行完成后也变为了resolved,所以p1,p2都进入了then方法。
这个方法和all()相反,那个率先改变的 Promise 实例的返回值,就传递给回调函数
const p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'p1')
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
resolve('p2');
})
.then(result => result)
.catch(e => e);
Promise.race([p1, p2])
.then(result => console.log(result,'then')) // p2 then
.catch(e => console.log(e,'catch'));
复制代码
若是将定时器去掉,你会发现一直执行的都是p1
Promise.allSettled()
方法接受一组 Promise 实例做为参数,包装成一个新的 Promise 实例。只有等到全部这些参数实例都返回结果,不论是fulfilled
仍是rejected
,包装实例才会结束。该方法返回的实例,状态老是fulfilled,不会变成rejected,接受的参数也是一个数组。
const promises = [
fetch('/api-1'),
fetch('/api-2'),
fetch('/api-3'),
];
await Promise.allSettled(promises);
removeLoadingIndicator();
复制代码
该方法接受一组 Promise 实例做为参数,包装成一个新的 Promise 实例返回。
Promise.any([
fetch('https://v8.dev/').then(() => 'home'),
fetch('https://v8.dev/blog').then(() => 'blog'),
fetch('https://v8.dev/docs').then(() => 'docs')
]).then((first) => { // 只要有一个 fetch() 请求成功
console.log(first);
}).catch((error) => { // 全部三个 fetch() 所有请求失败
console.log(error);
});
复制代码
以上就是回顾的全部知识点,有不足指出,还请多多指教!!!