promise代表了一个异步操作的最终结果,主要是通过then方法来注册成功以及失败的情况



Promise用处:
1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列 

通俗的说promise就是实现我们所期望的顺序去执行复杂代码。

解决ajax的回调地狱,为了代码的可读性可维护性,出现了Promise构造函数。



Promise的三种状态:


  • pending 等待中、进行中,表示还没有返回结果;
  • resolved(fulfilled) 已经完成返回了结果,可以继续往下执行;
  • rejected 表示得到了结果但是并不是我们想要的,所以拒绝执行。

.then()    .catch()  拿到的都是 Promise  构造函数内第一次执行的结果


const promise = new Promise((resolve, reject) => {
  resolve("success1");
  reject("error");
  resolve("success2");
});
promise
.then(res => {
    console.log("then: ", res);
  }).catch(err => {
    console.log("catch: ", err);
  })
// then:success1
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('timer')
    resolve('success')
  }, 1000)
})
const start = Date.now();
promise.then(res => {
  console.log(res, Date.now() - start)
})
promise.then(res => {
  console.log(res, Date.now() - start)
})
 
//'timer'
//'success' 1001
//'success' 1002

// Promise 的 .then 或者 .catch 可以被调用多次,但这里Promise构造函数只执行一次
// promise 内部状态一经改变,并且有了一个值,
// 那么后续每次调用 .then 或者 .catch 都会直接拿到该值。

 



Promise 构造函数,第一个参数是函数,会立即执行,用来处理Promise的状态变化。该函数的两个参数都是可选函数,resolve函数是将状态处理为resolved成功的,reject函数是将状态处理为rejected。


new Promise(function(resolve, reject) {
   if (typeof num == 'number') {
     resolve();
   } else {
     reject();
   }
 }).then(function() {
     console.log('参数是一个number值');
  }, function() { console.log('参数不是一个number值’) }
)


Promise结合setTimeout

setTimeout不管你设定多少时间,有一个4ms的最短时间延迟,最少都要间隔4ms才运行里面的回调。而Promise的异步没有这个问题。Promise所在的异步队列优先级要高于setTimeOut。

setTimeout(() => {
  console.log(7)
}, 0)
new Promise((resolve, reject) => {
  console.log(3);
  resolve();
  console.log(4);
}).then(() => {
  console.log(6)
})
console.log(5)

// 执行结果3,4,5,6,7


Promise中的then、catch、finally



.then()


    1. .then() 执行结果返回一个 Promise 对象,若返回非 promise 的值也会被包裹成 promise 对象


Promise.resolve().then(() => {
  return new Error('error!!!') //return Promise.resolve(new Error('error!!!'))
}).then(res => {
  console.log("then: ", res)
}).catch(err => {
  console.log("catch: ", err)
})

//"then: " "Error: error!!!"


    2. .then() 接收两个可选函数参数,第一个是处理成功的函数,第二个是处理失败的函数。若 传入非函数参数则会发生值透传。


Promise.reject('err!!!')
  .then((res) => {
    console.log('success', res)
  }, (err) => {
    console.log('error', err)
  }).catch(err => {
    console.log('catch', err)
  })
//'error','err!!!'  reject('err!!!')会进then()的第二个参数方法内
Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)
// 1 发生透传 resolve(1)直接传给最后一个then发法


    3. .then  或  .catch  返回的值不能是 promise对象本身,否则会造成死循环


const promise = Promise.resolve().then(() => {
  return promise;
})
promise.catch(console.err)

//Uncaught(in promise)
//TypeError: Chaining cycle detected for promise #<Promise>



.catch()


         .catch 不管被连接到哪里,都能捕获上层未捕捉过的错误


         .then  或  .catch  返回的值不能是 promise 本身,否则会造成死循环


         .then  或者  .catch  中  return  一个  error  对象并不会抛出错误,不会被后续的  .catch  捕获



const promise = new Promise((resolve, reject) => {
  reject("error");
  resolve("success2");
});
promise
.then(res => {
    console.log("then1: ", res);
  }).then(res => {
    console.log("then2: ", res);
  }).catch(err => {
    console.log("catch: ", err);
  }).then(res => {
    console.log("then3: ", res);
  })
 
//"catch: " "error" 
// 【catch不管被连接到哪里,都能捕获上层未捕捉过的错误
//"then3: " undefined
// 【catch捕获到错误后也会返回一个promise,所以后面then方法会继续执行
// 如果想要阻止后续代码继续执行,可使用 throw new Error 向外抛出错误,
// 或者使用promise的reject()。



.finally()


  1. .finally()不管 Promise对象最后的状态如何都会执行
  2.  .finally()的回调函数不接受任何参数,也就是 .finally()函数中是没法知道 Promise最终的状态是 resolved还是 rejected的
  3. .finally() 也是返回一个 Promise对象, 最终返回的默认是 上一次的 Promise 对象值 ,不过如果抛出的是一个异常则返回异常的 Promise 对象。


Promise中的all和race


Promise.all() 接收一组异步任务,当所有异步任务执行完成之后,才可以调 .then() 。 结果数组的顺序和 Promise.all() 接收到的数组顺序一致!!!



Promise.race() 也接收一组异步任务,不同的是, race() 只取第一个先执行完的异步任务结果 ,就调 .then()。 其他异步任务仍在执行,但执行结果会被丢弃。



all和race传入的数组中如果有抛出异常的异步任务,那么只有最先抛出的错误会被 then的第二个参数或者后面的 catch捕获;但并不会影响数组中其它的异步任务的执行。