最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 深度解析Promise(一)

    正文概述 掘金(小雯的老公)   2021-02-06   320

    Promise是什么

    Promise是一种异步编程的解决方案,是一个构造函数,具有all、reject、resolve这几个静态方法,原型上有then、catch等方法

    Promise具有两大特征: (1) 对象的状态不受外界影响。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态 (2) 状态一旦改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况其中之一发生,状态就不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果状态改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果

    下面是一个简单的Promise用法

    const promise = new Promise((resolve,reject) =>{
    	setTimeout(()=>{
    		console.log('promise已经执行')
    		resolve({say:'这是成功执行的结果'})
    	},3000)
    })
    

    我们将上面一段代码放到浏览器控制台中去调试一下,看看得到的结果是什么,会发现在3秒之后控制台打印出

    // promise已经执行
    

    其中执行过程是:执行了一个异步操作,也就是setTimeout,3秒后,输出“promise已经执行”,并且调用resolve方法

    注意!我只是new了一个对象,并没有调用它,我们传进去的函数就已经执行了,所以我们用Promise的时候一般是放在一个函数中,在需要的时候去执行这个函数,如:

    <div onClick={handleClick}>点击执行异步方法<div>
    const handleClick = ()=>{
    	const promise = new Promise((resolve,reject) =>{
    		setTimeout(()=>{
    			console.log('promise已经执行')
    			resolve({say:'这是成功执行的结果'})
    		},3000)
    	})
    	return promise
    }
    

    上面这样调用handleClick方法后,会return出Promise对象,也就是说,执行这个函数我们得到了一个Promise对象,接下来就可以用Promise对象上的then、catch方法了,这就是Promise的强大之处了

    then方法

    看下面的代码:

    handleClick().then(result=>{
    	console.log(result)
    })
    
    // {say: "这是成功执行的结果"}
    

    你可能会觉得在这个和写一个回调函数没有什么区别;那么,如果有多层回调该怎么办?如果callback也是一个异步操作,而且执行完后也需要有相应的回调函数,该怎么办呢?Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作:

    const promise2 = new Promise((resolve,reject)=>{
    	setTimeout(()=>{
    		resolve('promise2执行成功的结果')
    	},3000)
    })
    
    handleClick()
    .then(result=>{
    	console.log(result)
    	return promise2
    })
    .then(result=>{
    	console.log(result)
    })
    

    以上是对promise的resolve用法进行了解释,相当于resolve是对promise成功时候的回调,它把promise的状态修改为fullfiled,那么,reject就是失败时候的回调,他把promise的状态修改为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调

    const handleClick = ()=>{
    	const p = new Promise((resolve,reject)=>{
    	   setTimeout(()=>{
    		    console.log('这里已经执行')
    		    reject('这是失败的结果')
    	   },3000)
    })
    	return p
    }
    
    handleClick().then(result=>{
    	console.log('成功:',result)
    },err=>{
    	console.log('失败:',err)
    })
    

    3秒后输出的结果是:

    //这里已经执行
    //失败: 这是失败的结果
    

    运行handleClick并且在then中传了两个参数,这两个参数分别是两个函数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。(也就是说then方法中接受两个回调,一个成功的回调函数,一个失败的回调函数,并且能在回调函数中拿到成功的数据和失败的原因),所以我们能够分别拿到成功和失败传过来的数据就有以上的运行结果

    catch方法

    与Promise对象方法then方法并行的一个方法就是catch,与try catch类似,catch就是用来捕获异常的,也就是和then方法中接受的第二参数rejected的回调是一样的,如下:

    const handleClick = ()=>{
    	const p = new Promise((resolve,reject)=>{
    	   setTimeout(()=>{
    		    console.log('这里已经执行')
    		    reject('这是失败的结果')
    	   },3000)
    })
    	return p
    }
    
    handleClick()
    .then(result=>{
    	console.log('成功:',result)
    })
    .catch(err=>{
    	console.log('失败:',err)
    })
    

    catch方法最大的作用是:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中

    finally方法

    直接看代码:

    const promise = new Promise(function(resolve, reject) {
        setTimeout(()=>{
          if (true){
            resolve('执行成功')
          } else {
            reject('error')
          }
        },1000)
      }).then(res=>{
        console.log(res);
      }).catch(err=>{
        console.log(err)
      }).finally(()=>{
        console.log('finally')
      });
    

    不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数

    静态all方法

    先看一下下面的代码:

    const p1 = ()=>{
    	const time = Date.now()
    	let p = new Promise((resolve,reject)=>{
    		setTImeout({
    			if(time%2===0){
    				resolve('p1执行成功返回值')
    			}else{
    				reject('p1失败返回值')
    			}
    		},1000)
    	})
    	return p
    }
    
    const p2 = ()=>{
    	const time = Date.now()
    	let p = new Promise((resolve,reject)=>{
    		setTImeout({
    			if(time%2===0){
    				resolve('p2执行成功返回值')
    			}else{
    				reject('p2失败返回值')
    			}
    		},2000)
    	})
    	return p
    }
    
    const p3 = ()=>{
    	const time = Date.now()
    	let p = new Promise((resolve,reject)=>{
    		setTImeout({
    			if(time%2===0){
    				resolve('p3执行成功返回值')
    			}else{
    				reject('p3失败返回值')
    			}
    		},3000)
    	})
    	return p
    }
    
    Promise.all([p1(),p2(),p3()]).then(result=>{
    	console.log(result)
    })
    

    Promise.all() 的作用是把多个 Promise 实例包装成一个新的 Promise 实例

    • 只有 p1、p2、p3 的状态都变为已成功, p 的状态才会变为已成功 ,此 pl 、p2 、p3 的返回值组成一个数组,传递给 p 的回调函数
    • 只要 pl 、p2、 p3 中有一个的状态变为已失败,p 的状态就会变为已失败,此时 pl 、p2、 p3 中第一个状态变为已失败的返回值传递给 p 的回调函数

    这样以后就可以用all并行执行多个异步操作,并且在一个回调中处理所有的返回数据,比如你需要提前准备好所有数据才渲染页面的时候就可以使用all,执行多个异步操作将所有的数据处理好,再去渲染

    静态race方法

    all是等所有的异步操作都执行完了再执行then方法回调,那么race方法就是相反的,顾名思义,谁先执行完成就先执行回调。先执行完的不管是进行了race的成功回调还是失败回调,其余的将不会再进入race的任何回调

    const p1 = ()=>{
    	const time = Date.now()
    	let p = new Promise((resolve,reject)=>{
    		setTImeout({
    			if(time%2===0){
    				resolve('p1执行成功返回值')
    			}else{
    				reject('p1失败返回值')
    			}
    		},1000)
    	})
    	return p
    }
    
    const p2 = ()=>{
    	const time = Date.now()
    	let p = new Promise((resolve,reject)=>{
    		setTImeout({
    			if(time%2===0){
    				resolve('p2执行成功返回值')
    			}else{
    				reject('p2失败返回值')
    			}
    		},2000)
    	})
    	return p
    }
    
    const p3 = ()=>{
    	const time = Date.now()
    	let p = new Promise((resolve,reject)=>{
    		setTImeout({
    			if(time%2===0){
    				resolve('p3执行成功返回值')
    			}else{
    				reject('p3失败返回值')
    			}
    		},3000)
    	})
    	return p
    }
    
    Promise.race([p1(),p2(),p3()]).then(result=>{
    	console.log(result)
    },err=>{
    	console.log(err)
    })
    

    静态方法resolve和reject

    直接看代码:

    // 情况一,Promise静态方法传入一个值
    Promise.resolve('foo')
    .then(function(res) {
        console.log(res)  // foo
    })
    
    // 等价于
    new Promise(function(resolve, reject) {
        resolve('foo')
    })
    
    // 情况二,Promise静态方法传入一个promise对象
    const promise = api('/api/users.json')
    const promise2 = Promise.resolve(promise)
    // promise的静态方法传入一个promise,那他会原样的返回传入的promise对象
    console.log(promise === promise2) // true
    
    // 情况三:传入一个对象,也带有then,且then函数的参数也包含onFullFiled和onRejected两种状态的回调,也是可以将其转换成对应的Promise对象的,如下:
    Promise.resolve({
        // 这种带then方法的对象,实现了一个thenable的接口,可以被then的对象;这在之前原生PROMISE对象没普及时,很多三方库封装promise对象时都会采用这种思想
        then: function(onFullFiled, onRejected) {
            onFullFiled('foo')
        }
    })
    .then(res => {
        console.log(res)  // foo
    })
    
    // 快速创建一定是失败的promise对象的静态方法
    Promise.reject(new Error())
    .catch(error => {
        console.log(error)
    })
    // 无论传入什么参数都会作为promise对象失败的原因
    Promise.reject(anything)
    .catch(err => {
        console.log(err)
    })
    

    好了,关于Promise的用法,在这里分享完了,接下来我们将进一步解析一下Promise的内在原理


    起源地下载网 » 深度解析Promise(一)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元