ccdat

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

基础语法
http://es6.ruanyifeng.com/#docs/promise
点评:
》注意理解Promise定义形式和调用形式的差别,定义时主要指定什么情况下(比如去后台查询到数据)可以resolve或reject,调用时通过then指定resovle状态下执行什么回调方法,从而避免传统的回调写法层次太深的陷阱。
》注意理解执行顺序,Promise 定义时立即执行,且此时调用resolve或reject方法不会阻止后续代码的执行,而then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,即在本轮事件循环的末尾执行。
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
console.log('Promise end');
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
输出为:
// Promise
// Promise end
// Hi!
// resolved
》Promise对象触发resolve回调方法(即then绑定的参数)的调用是内部状态化,这个变化可以是主动的(调用resolve(参数是普通的值)),也可以是被动的(调用resolve(参数为另一个Promise对象)),这时其内部状态受另一个Promise对象的内部状态的影响。

》Promise内部状态一旦变为Fullfilled就不会再变,且then绑定的两个回调方法中返回的值,会自动包装成一个已resolved的promise,从而会传递给链式绑定的下一个then方法的成功回调函数里面去,并且上一个then回调函数返回的数据可被下一个then的回调函数接收。因此,不要在then方法里面定义 reject 状态的回调函数(即then的第二个参数),总是使用catch方法。因为reject回调中throw的error也是resolved状态而catch不住,除非不是throw new Error('error!!!')而是return Promise.reject(new Error('error!!!'))。详细分析参见下面的“最佳实践”。
// good
promise
.then(function(data) { //cb
// success
return newdata // 这里返回的数据可被下一个then回调接收
})
.then(function(data) { //cb
// success
})
.catch(function(err) {
// error
});
注意Node目前如果没有使用catch方法指定错误处理的回调函数,Promise对象抛出的错误不会传递到外层代码,即不会有任何反应。未来Node有计划如果 Promise 内部有未捕获的错误,会直接终止进程。
一般总是建议,Promise 对象后面要跟catch方法,这样可以处理 Promise 内部发生的错误。catch方法返回的还是一个 Promise 对象,因此后面还可以接着调用then方法。

》有时需要将现有对象转为 Promise 对象,Promise.resolve()方法就起到这个作用。
Promise.resolve()等价于下面的写法。
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))

Promise.resolve方法的参数分成四种情况。
(1)参数是一个 Promise 实例
如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。

(2)参数是一个thenable对象
Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};

let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
});
上面代码中,thenable对象的then方法执行后,对象p1的状态就变为resolved,从而立即执行最后那个then方法指定的回调函数,输出 42。

(3)参数不是具有then方法的对象,或根本就不是对象
如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的 Promise 对象,状态为resolved。
const p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
上面代码生成一个新的 Promise 对象的实例p。由于字符串Hello不属于异步操作(判断方法是字符串对象不具有 then 方法),返回 Promise 实例的状态从一生成就是resolved,所以回调函数会立即执行。Promise.resolve方法的参数,会同时传给回调函数。

(4)不带有任何参数
Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。

同理,Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。

异步加载图片示例:
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();

});

return promise;
};

getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});

》Bluebird 是一个功能丰富而且性能优异的 Promise 实现
https://www.ibm.com/developerworks/cn/web/wa-lo-use-bluebird-implements-power-promise/index.html

最佳实践
https://segmentfault.com/a/1190000014747362?utm_source=tag-newest

posted on 2019-10-21 07:44  ccdat  阅读(117)  评论(0编辑  收藏  举报