美文网首页
ES6学习笔记(16)之 Promise

ES6学习笔记(16)之 Promise

作者: 苦苦修行 | 来源:发表于2019-09-30 10:22 被阅读0次

参考:ECMAScript 6 入门

promise对象的特点:

  • 对象的状态不受外界影响,只能内部决定。(三种状态:pending, fulfilled, rejected)
  • 一旦状态改变,就不会再变。
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
  • 一旦新建它就会立即执行,无法中途取消。
  • 跟传统的try/catch代码块不同的是,如果没有使用catch方法指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应。(也就是说,即使promise内部有错误,程序也不会崩溃;想想其它的错误,如果不被catch住,程序就报错中断了)
const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行会报错,因为x没有声明
    resolve(x + 2);
  });
};

someAsyncThing().then(function() {
  console.log('everything is great');
});

setTimeout(() => { console.log(123) }, 2000);
// Uncaught (in promise) ReferenceError: x is not defined
// 123
  • 调用resolve或reject并不会终结 Promise 的函数的执行。
new Promise((resolve, reject) => {
  resolve(1); // 最好在此处return,比如:return resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
console.log(3);
// 2
// 3
// 1
  • resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例
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

解释:(我的理解:then方法只接受确定的状态?)

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

  • then方法返回的是一个新的Promise实例
getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL); // 又返回一个promise对象,该对象的返回结果将在下一个then中处理
}).then(function (comments) {
  console.log("resolved: ", comments);
}).catch(function (err){ 
//该catch方法有可能捕获第一个promise对象的错误,也有可能捕获第二个promise的错误
//Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。
  console.log("rejected: ", err);
});

promise的几个API的介绍:

Promise.prototype.finally()

  • ES2018(ES9)的标准,ES6中还没有。
  • 无论成功失败都执行的操作。

Promise.all()

  • Promise.all方法的参数可以是数组,比如Promise.all([p1, p2, p3])
  • p1、p2、p3都是 Promise 实例,如果不是,就会先调用Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。
  • 参数也可以是具有 Iterator 接口的对象,且返回的每个成员都是 Promise 实例。
  • p1, p2, p3都成功时all方法才成功,只要有一个失败,all方法就失败。

Promise.race()

  • 参数要求同Promise.all()
  • p1, p2, p3谁先执行完有结果,race 的 then(或catch)方法就执行谁的,这就体现出了赛跑的特点。

Promise. resolve()

  • 将现有对象转为 Promise 对象
  • 可以接受什么参数呢?
    1)如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
    2)如果参数是一个thenable对象。thenable对象指的是具有then方法的对象,比如下面这个对象。
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

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

3)参数为一般的对象,或根本不是对象。作为返回值返回。(如果参数为空,可以认为返回undefined)

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

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

Promise. reject()

  • Promise. resolve()的不同:
    Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数
const thenable = {
  then(resolve, reject) {
    reject('出错了');
  }
};

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})
// true

Promise.try()
作用:将同步异步方法统一处理,可以更好地管理异常。

function getUsername(userId) {
  return database.users.get({id: userId})
  .then(function(user) {
    return user.name;
  });
}

上面代码中,database.users.get()返回一个 Promise 对象,如果抛出异步错误,可以用catch方法捕获,就像下面这样写。

database.users.get({id: userId})
.then(...)
.catch(...)

但是database.users.get()可能还会抛出同步错误(比如数据库连接错误,具体要看实现方法),这时你就不得不用try...catch去捕获。

try {
  database.users.get({id: userId})
  .then(...)
  .catch(...)
} catch (e) {
  // ...
}

上面这样的写法就很笨拙了,这时就可以统一用promise.catch()捕获所有同步和异步的错误。

Promise.try(() => database.users.get({id: userId}))
  .then(...)
  .catch(...)

相关文章

网友评论

      本文标题:ES6学习笔记(16)之 Promise

      本文链接:https://www.haomeiwen.com/subject/qmxjyctx.html