参考: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(...)
网友评论