整理笔记--Promise

Promise 是异步编程的一种解决方案。

Promise对象两个特点:

对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

一旦状态改变,就不会再变。称为 resolved[已定型]。
从pending变为fulfilled 或者 从pending变为rejected

Promise缺点:

无法取消 Promise ,一旦新建它就会立即执行,无法中途取消。
如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

一、基础用法

//新建promise对象   两个参数resolve, reject
const promise = new Promise(function(resolve, reject) {
  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});


promise
.then( //promise的resolved回调函数
    result => {console.log("resolved: ", result)},  //then的第一方法成功回调,
    err => console.log("rejected: ", err)  //then的第二个失败回调 (可选) 不推荐 更推荐在catch捕获错误
.catch(error => {···}) //promise的resolved回调函数
.finally(() => {···}); //在执行`then`或`catch`后,都会执行`finally`回调

二、Promise.prototype.then()

第一个参数是resolved状态的回调函数,
第二个参数(可选)是rejected状态的回调函数

getJSON("/post/1.json").then(
  post => getJSON(post.commentURL)
).then(
  comments => console.log("resolved: ", comments),
  err => console.log("rejected: ", err)
);

第一个`then`方法指定的回调函数,返回的是另一个`Promise`对象。
第二个`then`方法指定的回调函数,就会等待这个新的`Promise`对象状态发生变化。如果变为`resolved`,就调用第一个回调函数,
如果状态变为`rejected`,就调用第二个回调函数。

三、Promise.prototype.catch()

Promise.prototype.catch() 是.then(null, rejection)或.then(undefined, rejection)的别名。

和then的二个参数一样用来指定reject的回调
但是比then的二个参数一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个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);
});

then的第二个函数与catch( )的区分

(1)Promise内部报错 则then的第二个函数和catch就近原则能捕获到

const promise = new Promise((resolve, rejected) => {
    throw new Error('test');
});

//情况一:既有第二个函数也有catch时 就近原则
promise.then(res => {
}, err => {
    console.log('我比较近我能捕获到',err);
}).catch(err1 => {
    console.log(err1);
});
运行结果:我比较近我能捕获到,test

//情况二:只有第二个函数或只有catch 那就是它能捕获

(2) then的第二个的函数捕获不了then中的第一个函数抛出的错误,而后续的.catch可以捕获。

Promise.resolve()
  .then(function success (res) {
    throw new Error('error')
  }, function fail1 (e) {
    console.error('fail1: ', e)~~~~
  })
  .catch(function fail2 (e) {
    console.error('fail2: ', e)
  })

运行结果:
fail2: Error: error
    at success (...)
    at ...

四、Promise.prototype.finally()

如服务器使用 Promise 处理请求,然后使用finally方法关掉服务器

server.listen(port)
  .then(result => {···})
  .finally(server.stop);

五、Promise的一些方法

Promise.all() 全返回回来才回调操作

// 生成一个Promise对象的数组
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON('/post/' + id + ".json");
});

Promise.all(promises).then(function (posts) {
}).catch(function(reason){
});

如果子promise没有报错了 但是子promise没有定义catch, 就会调用promise.all的catch。

Promise.race() 只要有一个回来就回调操作

// 有一个图片加载完就添加到页面
  function loadImg(src){
    return new Promise((resolve,reject)=>{
      let img=document.createElement('img');
      img.src=src;
      img.onload=function(){
        resolve(img);
      }
      img.onerror=function(err){
        reject(err);
      }
    })
  }

  function showImgs(img){
    let p=document.createElement('p');
    p.appendChild(img);
    document.body.appendChild(p)
  }

  Promise.race([
    loadImg('http://www.baidu.com/1.png'),
    loadImg('http://www.baidu.com/567751/2.png'),
    loadImg('http://www.baidu.com/567751/3.png')
  ]).then(showImgs)

Promise.resolve( ) 转为Promise对象

(1)参数是一个 Promise 实例 原封不动地返回这个实例
(2)不带有任何参数 直接返回一个resolved状态的 Promise 对象
(3)参数是一个thenable对象(即具有then方法的对象)
Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。

//`thenable`对象指的是具有`then`方法的对象
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);
p1.then(function(value) {
  console.log(value);  // 42
});

(4)参数不是具有then方法的对象,或根本就不是对象
如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的 Promise 对象,状态为resolved

const p = Promise.resolve('Hello');

p.then(function (s){
  console.log(s)
});
// Hello

Promise.reject( ) 转为Promise对象 且状态是rejected

和Promise.resolve方法一样,Promise.reject方法产生的Promise对象的状态是rejected的。

const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))

p.then(null, function (s) {
  console.log(s)
});
// 出错了

mark一下 仅供参考 欢迎更正补充 Thanks


参考资料:
阮一峰:https://es6.ruanyifeng.com/?search=String.raw&x=0&y=0#docs/promise#Promise-all
关于promise的十道题目:https://juejin.im/post/5a0406...
性感的Promise,拥抱ta然后扒光ta:https://juejin.im/post/5ab20c...
通俗易懂的Promise:https://juejin.im/post/5afe6d...

阅读 284

推荐阅读
喈喱前端笔记
用户专栏

学习的付出 从不欺人

4 人关注
30 篇文章
专栏主页