转载自: http://www.lht.ren/article/3/
Promise是什么呢?依据ecma-262的定义:
Promise是一个被用于延时盘算的终究效果的占位符
(A Promise is an object that is used as a placeholder for the eventual results of a deferred (and possibly asynchronous) computation.)
这个怎样明白呢
比如说,我要去麦当劳买点吃的,下单今后人家会先给你一个定单号,等人家外卖做好了,会提醒你,并用谁人定单小票来调换你真正的食品,在这时刻,谁人定单小票就是你这顿饭的占位符。
回到Promise,它有三种状况,分别为完成,谢绝和待决定,
而待决定的状况代表它还没有被完成或许是谢绝,也就是说,如果它一向都是处于待决定的状况,意味着代码永久都不会继承往下实行
所以下面这段代码永久都实行不到finish
new Promise((resolve, reject) => {
console.log('waiting');
document.writeln('waiting');
}).then((msg) => {
console.log('finish');
});
也就是意味着,必需显现的实行resolve()或许是reject,递次才会继承往下实行。
那怎样处置惩罚这个题目呢,实在很简单,决定一下就好了嘛,哈哈~~
或许给Promise设置一个超时时候,看下面的代码:
function timeoutPromise(delay) {
return new Promise( function(resolve,reject){
setTimeout( function(){
reject( "Timeout!" );
}, delay );
} );
}
Promise.race([
new Promise(() => {
console.log('waiting...');
}),
timeoutPromise(3000)
]).catch((msg) => {
console.log(msg);
})
这段代码呢,会先守候5秒,然后会打印出一个毛病”Timeout”,在这里,Promise.race()现实上就是竞态的,谁先决定,其他的就会被扬弃。所以我们三秒钟后决定一个谢绝,剩下谁人promise自动被扬弃了
说到毛病处置惩罚了,思索下面的代码:
new Promise((resolve, reject) => {
foo.bar();
}).then((msg) => {
console.log(msg);
}, null).then((msg) => {
console.log(msg);
}, (err) => {
console.log(err);
});
这段代码,很明显foo不是对象,所以会报ReferenceError,所以呢,会自动决定为reject,然后他紧接着的谁人then没有谢绝处置惩罚回调,然后接着往下通报毛病,直到有reject回调为止,如果一向都没有reject回调呢,他就会在全局抛出一个未捕捉的非常。
那末如果在Promise决定屡次呢,现实上只要第一次决定见效,也就是说,只能有一种决定见效,又胜利又失利,或许胜利屡次,失利屡次听着就不靠谱是吧,思索下面的代码
new Promise((resolve, reject) => {
resolve();
reject();
console.log('exec finish');
}).then((msg) => {
console.log('resolve');
}, (err) => {
console.log('reject');
});
运转效果是输出exec finish 和resolve,因为第一次决定为resolve, 所以reject决定就被扬弃了
人人想一下,决定后对应的then内里的回调函数是同步照样异步的呢,思索下面这个题目:
console.log(0);
let p = new Promise((resolve, reject) => {
console.log(1);
resolve();
console.log(2);
})
console.log(3);
p.then((msg) => {
console.log(4);
});
console.log(5);
他的效果是 1 2 3 5 4
答案很显然啦,是异步的!现实受骗决定今后,就会把它放到一个异步行列里挪用
那为何要这么设想呢,会给我们带来什么优点呢,思索下面这个题目
function getResult() {
console.log(a);
}
function opt() {
if (isAsync) {
setTimeout(() => {
getResult();
}, 0);
} else {
getResult();
}
}
var a = 0;
var isAsync = false;
opt();
a++;
isAsync = true;
opt();
a++;
他的效果输出的是0 2,那为何不是0, 1,现实上就是因为因为同步和异步的的不确定性致使的,也叫zalgo,所以呢,要想消弭他们的不确定性,必需就让他内里的代码要么都是同步,要么都是异步,这也是then为何是异步的缘由了
关于then,另有一个题目,就是then的返回值是什么,来继承看题目
var p = Promise.resolve( 21 );
var p2 = p.then( function(v){
return v * 2;
});
console.log(p2);
经由历程他的效果,你很轻易就能够看出来,then的返回值是一个Promise,那末,这个then回调是否是能够这么明白呢?
function callback() {
return Promise.resolve(42);
}
如果是的话,那末我们就研究一下Promise.resolve()的特征,然后then()同理就能够是吧
那末我们如今就研究一下Promise.resolve()的一些特征:
如果向Promise.resolve()通报一个非Promise,非thenable的马上值,就会马上获得这个值添补的Promise,这个有三个关键字,非Promise,非thenable和马上值
如果向Promise.resolve()通报一个真正的promise,那末就会返回这个Promise,又一个例子,很好明白
var p = Promise.resolve(42);
var p2 = Promise.resolve(p);
console.log(p === p2); // true
如果向Promise.resolve()通报一个非Promise的thenable值,那末就会睁开这个值,并且在睁开历程会延续到提掏出一个详细的Promise终究值
人人应当会有一点迷惑,thenable是什么,这段话是什么意义
var obj = {
then(resolve, reject) {
resolve(42);
}
};
Promise.resolve(obj).then((msg) => {
console.log(msg); //42
});
好了,Promise.resolve()特征讲完了,then返回值同理
同理完了今后呢,就会涌现一些比较有意义的用法
起首就是链式挪用,比如说
var p = Promise.resolve( 21 );
var p2 = p.then( function(v){
console.log( v ); // 21
// 用值42添补p2
return v * 2;
} );
// 衔接p2
p2.then( function(v){
console.log( v ); // 42
} );
很简单吧,就不赘述了。
另有一个比较有意义,就是Promise完成同步实行,也就是前一个then如果是异步的话,它必需操纵完成后,才会实行背面的then,罕见的写法是如许的
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('exec in promise it');
resolve();
}, 1000);
}).then(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('exec in then it');
resolve();
}, 1000);
});
});
这个先过一秒输出第一句话,再过一秒输出第二句话
这个的道理现实上方才Promise.resolve()的第二条,如果返回的是Promise,那末会直接返回这个Promise,在这里,直接返回return的这个Promise后,就会守候这个Promise决定,在一秒后决定完,就实行背面的then
末了一个有关then的学问点了:
一个Promise决定后,这个Promise上一切的经由历程then()注册的回调都邑鄙人一个异步时候节点上顺次被马上挪用,这些回掉中恣意一个都没法影响或许耽搁对其他回调的挪用
var p = new Promise((resolve, reject) => {
resolve();
});
p.then( function(){
p.then( function(){
console.log( "C" );
} );
console.log( "A" );
} );
p.then( function(){
console.log( "B" );
} );
// a b c
这个的重点现实上是这些决定回调都被到场到了一个行列中,输出的递次恰好现实上就代表了他们到场行列后的先后递次
参考书本《你不知道的Javascript中卷》