Promise复习

这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战前端

复习Promise知识,关于它的概念,使用方式等,还有注意事项。 参考依然是阮一峰老师的 ESCMAScript6入门 es6.ruanyifeng.com/ ,写它的缘由是在项目中能常常的使用到Promise作异步处理,,但对它并无系统性的了解。vue

Promise对象

概念

简单说下,Promise是一种js单线程的异步处理方案,在对后端的接口请求中咱们常常会用到,相信大多数前端都对这个不陌生。ES6将Promise进行来便准规范。es6

状态

promise有三种状态,而且具有了状态不受干扰以及状态一旦改变就不会再变的特性。正则表达式

三种状态分别是mongodb

  1. pending进行中
  2. fulfilled已成功
  3. rejected已失败

须要注意的是,一旦执行,中途就没法取消,若是不设置回调函数,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: 错了
复制代码

两个比较,咱们就能够清晰认识到这一点。

then()和catch()

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

finally()方法用于指定无论 Promise 对象最后状态如何,都会执行的操做。该方法是 ES2018 引入标准的。相对用的比较少,在特定环境下,finally 也会有奇效,具体看业务场景。

all()

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'));
复制代码

image.png

再看下面的例子

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'));
复制代码

image.png

这个彷佛咱们以前所说的不一致,主要是由于p2中使用了catch, p2首先进入rejected,可是由于有本身的catch方法,方法会返回一个新的实例,p2指向的实际是这个实例。实例执行完成后也变为了resolved,所以p1,p2都进入了then方法。

race()

这个方法和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

allSettled()

Promise.allSettled()方法接受一组 Promise 实例做为参数,包装成一个新的 Promise 实例。只有等到全部这些参数实例都返回结果,不论是fulfilled仍是rejected,包装实例才会结束。该方法返回的实例,状态老是fulfilled,不会变成rejected,接受的参数也是一个数组。

const promises = [
  fetch('/api-1'),
  fetch('/api-2'),
  fetch('/api-3'),
];

await Promise.allSettled(promises);
removeLoadingIndicator();
复制代码

any()

该方法接受一组 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);
});
复制代码

以上就是回顾的全部知识点,有不足指出,还请多多指教!!!

相关文章

let,const复习 juejin.cn/post/699147…

初学koa搭建项目 juejin.cn/post/698756…

正则表达式总结 juejin.cn/post/698615…

flex布局总结 juejin.cn/post/698497…

mongodb基础用法 juejin.cn/post/698364…

vue3搭建管理后台-项目搭建 juejin.cn/post/696802…

工厂模式,构造器模式和原型模式 juejin.cn/post/695794…

相关文章
相关标签/搜索