ES6学习笔记(3)Promise1

promise
用来解决异步的东西。
避免回调地狱,支持异步的链式操作,其实我在使用angular的时候就发现,其实promise也有多层嵌套,但是这个嵌套实际上只有两层。可以很好的进行理解。
为什么会出现多级嵌套的问题。
现在有一个A函数,他是一个异步的,http的
那么我们的A函数有
A(data,success,err)
suc跟err是一个回调函数
如果b要使用A,b本身也是一个异步的函数
B(data,success,err)
C要用B,C也是一个异步的函数那么就有
C(data,success,err)
如果我们要定义C则是会进入回调地狱,因为在c里面不仅仅要写自己的回调函数,还要写AB的回调函数,这个是很显然的不科学的,会陷入回调地狱

promise
关键字 resolve reject then
对于Promise对象来说

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

这个话或许可以回答下疑惑,reject跟reslov是状态而不仅仅是函数。
可以认为.then函数的实现方式是
then(resolve,reject){
    if(this.resolve){resolve}
    else(thise.reject)
}

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
如果某些事件不断地反复发生,一般来说,使用  Stream 模式是比部署Promise更好的选择。

基本用法
const promise  =  new  Promise ( function ( resolve ,  reject )  {
// ... some code
if  ( /* 异步操作成功 */ ) {
resolve ( value ) ;
}  else  {
reject ( error ) ;
} } ) ;
可以看到这个跟我们的$q的区别是
promise是$q的defer的一个属性,而这里promise就是promise
所以也就不是defer.resolve了而是resolve
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

可以看到resolve函数跟reject函数不可以同时进行部署。
var  p = new  Promise ( function ( resolve , reject ){
setTimeout (()  =>  {
reject ( "hhhh" );
resolve ( "zzzz" );
},  1000 );
})
p . then ( function ( res ){
console . log ( res );
}, function ( res ){
console . log ( res );
})

这段代码很有意思,因为,如果我们先把reject放到前面,这个时候会执行reject,而如果是resolve,则是执行resolve,也可以看出,状态是不会改变的,即使后面用了改变状态的函数,但是也没有直接报错
promise创建以后就会立即执行
其实这里总觉得有点废话的样子。。。当然应该是立即执行,因为他是一个构造函数可以这样认为大概。不对,这样我们最好还是把一个promise对象当成一个函数的返回值来使用
function  timeout ( ms ) {
return  new  Promise (( resolve ,  reject )  =>  {
console . log ( "zzz" );
setTimeout ( resolve ,  ms ,  'done' );
});
}
var  p  =  new  Promise (( resolve ,  reject )  =>  {
console . log ( "zzz" );
setTimeout ( resolve ,  ms ,  'done' );
});
timeout ( 100 ). then (( value )  =>  {
console . log ( value );
});


这两个,第一个p在一创建的时候就执行了,而第二个必须要进行调用函数,如果我们所有的网络请求都是跟p一样,那么一开始就会请求所有的接口,这样是不必要的


突然想到个问题,那就是其实我们的promise对象里面的reslove跟reject方法是不能共存的吧,他不能使用promise.reject来进行调用,而是现在是什么状态就调用什么。里面只能有一个函数

promise是可以进行链式调用的
并用其去解决回调函数的问题
感觉还是很难懂很难去理解一下。
--
但是现在有点理解了,我们的函数其实是要进行数据处理的,也就是本身其实是,获得一个数据,对这个数据进行操作,但是可能我们要获取数据A需要先获取数据B,要获取数据B需要先获取数据C而这个每一个都是异步的。所以我们执行getA的时候需要进行三次异步操作,这三次异步是反应在函数定义里面的,但是实际上,我们应该更加的纯粹一点。以前的时候C的是
getC (data)={
    ajaxA(data){
        ajaxB(data){
            ajaxC(data)

而现在是
getC (data)=
    ajaxC(data)
然后在执行的时候传入
getC(getB.then(getA)
也就是把回调放到了执行的时候再调用。

但是这里我觉得应该可以维持到两层的链子
不然的话不是把回调地狱从定义放到了使用上来了,这个样子不是更加的不好吗。
注意传统的异步调用是不可以实现最多两层的

function setTimeout0 (){
setTimeout (() => {
return '1'
}, 1000 );
}
function setTimeout1 (){
setTimeout (() => {
return setTimeout0 ();
}, 1000 );
}
function setTimeout2 (){
setTimeout (() => {
return setTimeout1 ();
}, 1000 );
}
console . log ( setTimeout2 ()); //undifend

function setTimeout0 () {
return new Promise ( function ( resolve , reject ) {
setTimeout (() => {
resolve ( "zzz" );
}, 1000 );
})
}
function setTimeout1 () {
return new Promise ( function ( resolve , reject ) {
setTimeout (() => {
setTimeout0 (). then ( function ( res ){
resolve ( res );
})
}, 1000 );
})
}
function setTimeout2 () {
return new Promise ( function ( resolve , reject ) {
setTimeout (() => {
setTimeout1 (). then ( function ( res ){
resolve ( res );
})
}, 1000 );
})
}

setTimeout2 (). then ( function ( res ) {
console . log ( res ); //zzz
});


这样其实就是可以进行控制了,这样就只需要两层的循环就可以解决问题了。
但是如果要链式调用要怎么写呢?
这里要注意的是,我们最后的调用过程,是跟我们前面的是完全相反的
function setTimeout0 ( data ) {
return new Promise ( function ( resolve , reject ) {
setTimeout (() => {
resolve ( data + '0' );
}, 1000 );
})
}
function setTimeout1 ( data ) {
return new Promise ( function ( resolve , reject ) {
setTimeout (() => {
resolve ( data + '1' );
}, 1000 );
})
}
function setTimeout2 ( data ) {
return new Promise ( function ( resolve , reject ) {
setTimeout (() => {
resolve ( data + '2' );
}, 1000 );
})
}
// 如果此时2的数据要来自1,1的数据要来自0,应该怎么进行处理呢?
setTimeout0 ( 'zzz' ). then ( function ( res ){
return setTimeout1 ( res );
}). then ( function ( res ){
return setTimeout2 ( res )
}). then ( function ( res ){
console . log ( res ); //zzz012
})

我们前面的思路是,要获取2的数据,就要先获取1的数据,要获取1的数据,就要先获取0的数据,
而这里的思路是,先获取0的数据,把0的数据给1,让2通过1的数据来获取2的数据
这样可以看出,实际上是更加的灵活。
因为如果我们使用前面那种方式得话,实际上有可能并不一定需要做三次请求,可能现在已经缓存下来了上一次请求的数据,可以直接拿来用了。


(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

这个话或许可以回答下疑惑,reject跟reslov是状态而不仅仅是函数。
可以认为.then函数的实现方式是
then(resolve,reject){
    if(this.resolve){resolve}
    else(thise.reject)
}

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
如果某些事件不断地反复发生,一般来说,使用  Stream 模式是比部署Promise更好的选择。

基本用法
const promise  =  new  Promise ( function ( resolve ,  reject )  {
// ... some code
if  ( /* 异步操作成功 */ ) {
resolve ( value ) ;
}  else  {
reject ( error ) ;
} } ) ;
可以看到这个跟我们的$q的区别是
promise是$q的defer的一个属性,而这里promise就是promise
所以也就不是defer.resolve了而是resolve
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

可以看到resolve函数跟reject函数不可以同时进行部署。
var  p = new  Promise ( function ( resolve , reject ){
setTimeout (()  =>  {
reject ( "hhhh" );
resolve ( "zzzz" );
},  1000 );
})
p . then ( function ( res ){
console . log ( res );
}, function ( res ){
console . log ( res );
})

这段代码很有意思,因为,如果我们先把reject放到前面,这个时候会执行reject,而如果是resolve,则是执行resolve,也可以看出,状态是不会改变的,即使后面用了改变状态的函数,但是也没有直接报错
promise创建以后就会立即执行
其实这里总觉得有点废话的样子。。。当然应该是立即执行,因为他是一个构造函数可以这样认为大概。不对,这样我们最好还是把一个promise对象当成一个函数的返回值来使用
function  timeout ( ms ) {
return  new  Promise (( resolve ,  reject )  =>  {
console . log ( "zzz" );
setTimeout ( resolve ,  ms ,  'done' );
});
}
var  p  =  new  Promise (( resolve ,  reject )  =>  {
console . log ( "zzz" );
setTimeout ( resolve ,  ms ,  'done' );
});
timeout ( 100 ). then (( value )  =>  {
console . log ( value );
});


这两个,第一个p在一创建的时候就执行了,而第二个必须要进行调用函数,如果我们所有的网络请求都是跟p一样,那么一开始就会请求所有的接口,这样是不必要的

猜你喜欢

转载自blog.csdn.net/aboyl/article/details/79232012
今日推荐