首页 前端知识 12.关于JS中的promise理解以及使用

12.关于JS中的promise理解以及使用

2024-03-11 10:03:45 前端知识 前端哥 197 703 我要收藏

一、什么是promise

Promise是一种异步编程的解决方案,用于处理异步操作并返回结果,从语法上看它是一个构造函数,从功能上看它是用来封装一个异步操作并可以获取它成功/失败的结果值。

1.概念

简单来说就是一个容器,里面保存着未来才会结束的事件( 通常是一个异步操作 )的结果。从语法上来说,Promise是个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作(定时器、ajax请求等)都可以用同样的方法进行处理。

2.特点

1、promise有三种状态 进行中(pending)、已成功(fulfilled)、已失败(rejected)、且promise必然处在这三种状态之中

2、一旦状态改变,就不会再改变,任何时候都可以得到这个结果。状态改变只有两种状态从pending变为fulfilled和从pending变为rejected。

二、用法

1.基本用法

  // Promise构造函数接受一个函数(执行器函数)作为参数,
  // 该函数的两个参数分别是resolve和reject。它们是两个函数,
  // 由 JavaScript 引擎提供,不用自己部署。
  const promise = new Promise(function (resolve, reject) {
    // ... some code

    if (/* 异步操作成功 */) {
      // 在异步操作成功时调用,并将异步操作的结果,作为参数value传递出去;
      resolve(value);
    } else {
      // 在异步操作失败时调用,并将异步操作报出的错误,作为参数error/reason传递出去。
      reject(error);
    }
  });

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

 promise.then(function(value) {
    // success
  }, function(error) {
    // failure
  });

then方法可以接受两个回调函数作为参数。

  • 第一个回调函数是Promise对象的状态变为resolved时调用。
  • 第二个回调函数是Promise对象的状态变为rejected时调用。
// 创建一个新的p对象promise
const p = new Promise((resolve, reject) => { // 执行器函数
  // 执行异步操作任务
  setTimeout(() => {
    const time = Date.now() 
    // 如果当前时间是偶数代表成功,否则失败
    if (time % 2 == 0) {
      // 如果成功,调用resolve(value)
      resolve('成功的数据,time=' + time)
    } else {
      // 如果失败,调用reject(reason)
      reject('失败的数据,time=' + time)
    }
  }, 1000);
})

p.then(
  value => { // 接收得到成功的value数据 onResolved
    console.log('成功的回调', value)  // 成功的回调 成功的数据
  },
  reason => { // 接收得到失败的reason数据 onRejected
    console.log('失败的回调', reason)    // 失败的回调 失败的数据
  }
)

2.Promise.prototype.then 方法

(onResolved, onRejected) => {}   指定两个回调(成功+失败)

onResolved 是成功的回调函数,onRejected是失败的回调函数

3.Promise.prototype.catch 方法

onRejected 函数: 失败的回调函数 (reason) => {}

catch是then的语法糖,相当于then(undefined, onRejected)

4.Promise.resolve方法  Promise.resolve(value) => {}

let p1 = Promise.resolve(521);
console.log(p1); // Promise {<fulfilled>: 521}

返回一个成功/失败的 promise 对象

value:传入一个promise或者成功的数据

如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果

let p2 = Promise.resolve(new Promise((resolve, reject) => {
    // resolve('OK'); // 成功的Promise
    reject('Error');
}));
console.log(p2);
p2.catch(reason => {
    console.log(reason);
})

5.Promise.reject 方法: Promise.resolve(reason) => {}

返回一个失败的 promise 对象

 let p = Promise.reject(521);
  let p2 = Promise.reject('iloveyou');
  let p3 = Promise.reject(new Promise((resolve, reject) => {
    resolve('OK');
  }));

  console.log(p);
  console.log(p2);
  console.log(p3);

 

Promise.resolve() / Promise.reject() 方法就是一个语法糖,用来快速得到Promise对象

6. Promise.all 方法: Promise.all(iterable) => {}

  • iterable:包含 n 个 promise 的可迭代对象,如 Array 或 String
  • 返回一个新的 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);
  result.then(res => {
    console.log(res, '打印结果');
  })

且用then回调函数参数也为数组

  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);
  result.then(res => {
    console.log(res);
  }).catch(msg => {
    console.log(msg);
  })

 

当有一个不成功时就会失败

Promise.all( ).then( )适用于处理多个异步任务,且所有的异步任务都得到结果时的情况。

使用场景:用户点击按钮,会弹出一个弹出对话框,对话框中有两部分数据呈现,这两部分数据分别是不同的后端接口获取的数据。弹框弹出后的初始情况下,就让这个弹出框处于数据加载中的状态,当这两部分数据都从接口获取到的时候,才让这个数据加载中状态消失。让用户看到这两部分的数据。

7. Promise.race方法:Promise.race(iterableiterableiterableiterableiterableiterableiterable) => {}

  • iterable:包含 n 个 promise 的可迭代对象,如 Array 或 String
  • 返回一个新的 promise, 第一个完成的 promise的结果状态就是最终的结果状态。
  // 谁先完成就输出谁(不管是成功还是失败)
  const p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(1)
    }, 1000)
  })
  const p2 = Promise.resolve(2)
  const p3 = Promise.reject(3)
  const pRace = Promise.race([p1, p2, p3])
  pRace.then(
    value => {
      console.log('race onResolved()', value)
    },
    reason => {
      console.log('race onRejected()', reason)
    }
  )

类似于Promise.all() ,区别在于 它有任意一个返回成功后,就算完成,但是 进程不会立即停止

使用场景:把异步操作和定时器放到一起,如果定时器先触发,认为超时,告知用户

8.promise关键点

如何改变promise的状态:通过resolve(value)、reject(reason)、 抛出异常 可以改变promise的状态

  const p = new Promise((resolve, reject) => {
    //resolve(1) // promise变为resolved成功状态
    //reject(2) // promise变为rejected失败状态
    throw new Error('出错了') // 抛出异常,promise变为rejected失败状态,reason为抛出的error
  })
  p.then(
    value => { },
    reason => { console.log('reason', reason) }
  )

 

9.promise链式调用 

promise 的 then()返回一个新的 promise, 可以开写成 then()的链式调用

  new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('执行任务1(异步)')
      resolve(1)
    }, 1000)
  }).then(
    value => {
      console.log('任务1的结果', value)
      console.log('执行任务2(同步)')
      return 2 // 同步任务直接return返回结果
    }
  ).then(
    value => {
      console.log('任务2的结果', value)
      return new Promise((resolve, reject) => { // 异步任务需要包裹在Promise对象中
        setTimeout(() => {
          console.log('执行任务3(异步)')
          resolve(3)
        }, 1000)
      })
    }
  ).then(
    value => {
      console.log('任务3的结果', value)
    }
  )

链式调用的原理:

因为then方法也会返回一个新的Promise, 然后这个Promise会根据它接收的参数,来决定状态, 如果接收到的不是一个Promise, 那么它就自动置为fullfill, 如果接收到的参数是Promise, 那么就将它的resolve函数放在接收到的Promise中的then方法执行, 所以就保证了只有接收到的参数的那个Promise执行完, 返回的的Promise才会执行,也就形成链式调用的过程

转载请注明出处或者链接地址:https://www.qianduange.cn//article/3577.html
标签
评论
发布的文章

jQuery之宽高

2024-04-05 09:04:19

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!