如果阅读有疑问的话,欢迎评论或私信!!
本人会很热心的阐述自己的想法!谢谢!!!
文章目录
- 回调中的信任问题
- 回调给我们带来的烦恼?
- 调用过早
- 调用过晚
- 调用的次数太少或太多
- 调用回调时未能成功传入参数
- 吞掉了可能出现的错误或异常
- Promise链式流
- 探索Promise异步模式抽象的变体——Promise.all篇
回调中的信任问题
什么是信任问题?先看下面的代码!
//这里是现在要进行的代码1
ajax("...",function(){
//这是是将来要执行的代码2
})
//这里是现在要进行的代码3
我们从1执行到3,中间的2交给了ajax进行回调,但是我们不知道ajax会什么时候调用。代码1
之后?还是代码3
之后?或许代码3
的可能性更大一些,但是也不排除代码1
的小概率事件,毕竟不是我们所能控制的。
上面中的情况我们会叫做控制反转(inversion of control)
,总而言之,意思就是把自己代码的控制权交给了第三方。
回调给我们带来的烦恼?
调用过早
我们可能打算在代码3
执行完之后再让代码2
执行。在上面的代码中,我们可以看到,代码2
可能在代码3
之前运行,这种情况就属于调用过早
。
我们通常会使用setTimeout(“…” , 0 )使这段代码中的语句立即执行,但是如今在ES6中,Promise帮我们已经解决了这个问题,不再需要自行设置hack。
调用过晚
调用过晚意思是我们有时希望代码2
可以在代码3
之前执行完毕,但是真实结果可能是代码2在代码3之后执行的概率更大些。
这种情况我们称之为调用过晚。
调用过早
和调用过晚
会使得我们的代码具有二义性
,在编写程序时,我们无法准确控制
代码执行的时间,也无法将执行时间提前
。但是我们可以将代码的执行统一后退
,将对代码决议完之后的结果
统一执行!Promise就是这么做的!!
回调调用过晚,导致未调用
这种情况也属于调用过晚,或许因为代码中存在javascript错误
,亦或者是其他错误
导致。而在ES6中的Promise,没有任何东西
可以阻止
Promise的决议
。Promise总会调用其自身的完成回调或拒绝回调的其中一个方法。
如果Promise本身永远不被决议呢?
Promise提供了一种成为竞态
的高级抽象机制:Promise.race()
该方法的参数为一个数组,数组中可以是Promise构造器,亦可以是立即值。在该方法中,都会通过Promise.resolve()
过滤。在数组中可以设置如下代码设置超时,引起拒绝回调。
function timeoutPromise(delay){
return new Promise(function(resolve,reject){
setTimeout(function(){
reject("超时了");
},delay)
})
})
调用的次数太少或太多
调用次数太少
是指前面的未调用
,在回调中,次数最少可以为1次。
调用次数过多
,是指回调被频繁引用
,例如:设置的定时器过多…
在Promise中,每个决议只能被决议一次
,无论后续再怎么调用,也只能得到相同的决议值。
调用回调时未能成功传入参数
要强调一句,Promise只能有一个决议值!
如果Promise没有显示决议,那么这个决议值是undefined,例如下面这个代码:
var p = new Promise(function(resolve,reject){
resolve();
})
p.then(
function fulfilled(msg){
console.log(msg); //undefined
},
function rejected(err){
console.error(err);
}
)
这里resolve
并没有传递参数。
tip:如果
多个参数
调用resolve(…)或者reject(…),除了第一个参数
被传入Promise中,其他参数会被默默忽略
。如果要传入多个参数
,只能使用对象
或一个数组
的形式传入。
吞掉了可能出现的错误或异常
我们先来看一下下面的代码!
var p = new Promise(function(resolve,reject){
foo.bar();
resolve(1);
})
p.then(
function fulfilled(msg){
console.log(msg)
},
function rejected(err){
console.error(err)
}
)
在这个例子中,我们会看到控制台打印出了下面这个错误:
ReferenceError: foo is not defined
at test.html:15:7
at new Promise ()
at test.html:14:14
由上所示:在出现javascript错误时,Promise会默认调用了拒绝回调
。
我们再看一个相似的代码:
var p = new Promise(function(resolve,reject){
resolve(1);
})
p.then(
function fulfilled(msg){
foo.bar();
console.log(msg)
},
function rejected(err){
console.error(err)
}
)
在这个例子中,我们会看到控制台打印出了下面这个错误:
Uncaught (in promise) ReferenceError: foo is not defined
at fulfilled (test.html:19:7)
Uncaught
中文意思是未能捕获
,即该异常没有被处理
。通常我们可能会想,为什么Promise检测到异常后不调用下面的rejected函数? 因为Promise有一个 重要原则:决议值一次决议,不会更改。我们不能因为爆出了异常,就使得该决议值成为了rejected。
解决该方法通常采用注册处理函数的方式解决,即在尾部使用catch()。该方法相当于以下代码:
catch = new Promise(function(resolve,reject){
reject();
})
Promise链式流
Promise中的链式流
探索Promise异步模式抽象的变体——Promise.all篇
探索Promise异步模式抽象的变体