JavaScript 中Promise 详解及方法

  1. 定义

   Promise里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

   特点:1.对象的状态不受外界影响;

         2.一旦状态改变就不会再变,且通过添加回调函数可以得到该结果。

   状态:1.pending(进行中)--> fulfilled(已成功)

         2.pending(进行中)--> rejected(已失败)

  1. 基本用法

  1.resolved:“未完成”-->“成功”

    rejected:“未完成”-->“失败”

function timeout(ms) {

  return new Promise((resolve, reject) => {

    setTimeout(resolve, ms, 'done');

  });}

timeout(3000).then((value) => {

  console.log(value);});//执行后,会在3000ms后打印出done

  

   2.promise新建后将会立即执行,而then方法指定的回调函数,要在当前脚本所有同步任务执行完才会执行。

let promise = new Promise(function(resolve, reject) {

  console.log('Promise');

  resolve();});

promise.then(function() {

  console.log('resolved.');});

console.log('Hi!');

// Promise

// Hi!

// resolved

3.如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是resolved或者rejected,那么p2的回调函数将会立刻执行。

const p1 = new Promise(function (resolve, reject) {

  // ...});

const p2 = new Promise(function (resolve, reject) {

  // ...

  resolve(p1);})

例:

const p1 = new Promise(function (resolve, reject) {

  setTimeout(() => reject(new Error('fail')), 3000)})

const p2 = new Promise(function (resolve, reject) {

  setTimeout(() => resolve(p1), 1000)})

p2

  .then(result => console.log(result))

  .catch(error => console.log(error))// Error: fail

p1是一个 Promise,3 秒之后变为rejectedp2的状态在 1 秒之后改变,resolve方法返回的是p1。由于p2返回的是另一个 Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态。所以,后面的then语句都变成针对后者(p1)。又过了 2 秒,p1变为rejected,导致触发catch方法指定的回调函数。

   4.调用resolvereject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolvereject的后面。所以,最好在它们前面加上return语句,这样就不会有意外。

new Promise((resolve, reject) => {

  return resolve(1);

  // 后面的语句不会执行

  console.log(2);})

*******************************************************

new Promise((resolve, reject) => {

  resolve(1);

  console.log(2);}).then(r => {

  console.log(r);});// 2// 1 //resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。

  1. Promise.prototype.catch()

   1.当返回一个 Promise 对象,如果该对象状态变为resolved,则会调用then()方法指定的回调函数;如果异步操作抛出错误,状态就会变为rejected,就会调用catch()方法指定的回调函数,处理这个错误。另外,then()方法指定的回调函数,如果运行中抛出错误,也会被catch()方法捕获。

2.Promise 在resolve语句后面,再抛出错误,不会被捕获,等于没有抛出。因为 Promise 的状态一旦改变,就永久保持该状态,不会再变了。

const promise = new Promise(function(resolve, reject) {

  resolve('ok');

  throw new Error('test');});

promise

  .then(function(value) { console.log(value) })

  .catch(function(error) { console.log(error) });// ok

   3.catch()方法返回的还是一个 Promise 对象,因此后面还可以接着调用then()方法。

Promise.resolve()

catch(function(error) {console.log('oh no', error);})

.then(function() {console.log('carry on');});

// oh no [ReferenceError: x is not defined]

// carry on

没有报错,跳过了catch()方法,直接执行后面的then()方法。

Promise.resolve().catch(function(error) {

  console.log('oh no', error);}).then(function() {

  console.log('carry on');});// carry on

  1. Promise.all(),Promise.any(),Promise.race()

   将多个Promise实例包装成一个新的Promise实例。其中:(1)只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。(2)只要p1p2p3之中有一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

   注意如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()catch方法。如果没有自己的catch方法,就会调用Promise.all()catch方法。

const p1 = new Promise((resolve, reject) => {

  resolve('hello');}).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)).catch(e => console.log(e));// ["hello", Error: 报错了]

********************************************************************

const p1 = new Promise((resolve, reject) => {

  resolve('hello');}).then(result => result);

const p2 = new Promise((resolve, reject) => {

  throw new Error('报错了');}).then(result => result);

Promise.all([p1, p2]).then(result => console.log(result)).catch(e => console.log(e));// Error: 报错了

Promise.any()只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;只有参数都变成rejected状态,包装实例才会变成rejected状态。

Promise.race()只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;只要有一个变成rejected状态,包装实例就会变成rejected状态。

  1. promise.resolve()

   将现有对象转为 Promise 对象

setTimeout(function () {

  console.log('three');}, 0);

Promise.resolve().then(function () {

  console.log('two');});

console.log('one');

// one

// two

// three

setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise.resolve()在本轮“事件循环”结束时执行,console.log('one')则是立即执行,因此最先输出。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值