概念:
promise是異步編程的一種解決方案.
? ? ? ? (就可以將異步操作以同步操作的流程表達(dá)出來(lái),避免了層層嵌套的回調(diào)函數(shù))
異步:之前實(shí)現(xiàn)異步操作的方式.①回調(diào)函數(shù)②事件觸發(fā)
作用:解決異步操作問(wèn)題.
特點(diǎn):
(1)對(duì)象的狀態(tài)不受外界影響.promise對(duì)象代表一個(gè)異步操作,
? ? ? ? ? ? 有三種狀態(tài): pending(進(jìn)行中).fulfilled(已成功),rejected(已失敗)
? ? ? ? ? ? 只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無(wú)法改變這個(gè)狀態(tài).
? ? ? ? (2)對(duì)象的狀態(tài),一旦改變,就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果.
? ? ? ? ? ? ?(promise對(duì)象的狀態(tài)改變,只有兩種可能:從pending變?yōu)閒ulfilled和從pendig變?yōu)閞ejected.)
基本用法:
(1)通過(guò)new promise對(duì)象可以創(chuàng)建promise實(shí)例
? const promise = new Promise(function (resolve,reject){? })
(2)參數(shù)說(shuō)明:promise對(duì)象接收一個(gè)函數(shù)做參數(shù),并且這個(gè)函數(shù)的參數(shù)分別是resolve和reject,它們是兩個(gè)函數(shù),由javascript引擎提供
(3)resolve函數(shù)的作用.在異步操作成功時(shí)調(diào)用,并將異步操作的結(jié)果,作為參數(shù)傳遞出去
(4)reject函數(shù)的作用.在異步操作失敗時(shí)調(diào)用,并將異步操作報(bào)出的錯(cuò)誤,作為參數(shù)傳遞出去
說(shuō)明:
promise實(shí)例生成以后,可以用then方法,分別指定成功和失敗的回調(diào)函數(shù)
分別利用回調(diào)函數(shù)和promise模擬1秒通信(在執(zhí)行完打印'hello',1s再打印'world')
①回調(diào)函數(shù)發(fā)法:? ?function ajax (callback){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log('hello')
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? setTimeout(function(){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?callback&&callback()
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? },1000)
? ? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ? ajax(function(){
? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log('world')
? ? ? ? ? ? ? ? ? ? ?}
②promise方法? ? ? ?function? ?ajax(){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log('hello')
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return new Promise(function(resolve,reject){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?setTimeout(function(){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? resolve()
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? },1000)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ajax().then(function(){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log('world')
? ? ? ? ? ? ? ? ? ? ? ? ? })
.then()是promise實(shí)例的一個(gè)方法,表示要執(zhí)行的下一步操作
promise實(shí)例的方法
(1)then(參數(shù)1,參數(shù)2)
作用:為promise實(shí)例添加狀態(tài)改變時(shí)的回調(diào)函數(shù)
? ? ? ? 參數(shù)1是成功的回調(diào)函數(shù),參數(shù)2是失敗的回調(diào)函數(shù)
? ? ? ? 返回值:then方法返回的是一個(gè)新的promise實(shí)例,.then方法可以采用鏈?zhǔn)讲僮?/p>
(2)catch()
作用:
指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù),作用等同于then方法的第二個(gè)參數(shù)
let ajax =? function(num){
return new Promise(resolve,reject)=>{
? ? ? ?if(num>5){
? ? ? ? ? ?resolve(num)
? ? ? ?}else{
? ? ? ? ? ? ?throw new Error('出錯(cuò)了')
? ? ? ?}
? })
}
ajax(2).then(function(num){
console.log(num)
}).catch(function(err){
console.log(err)
}
Promise風(fēng)格的ajax
? ? ? ? ? ? ? ? ? ? function promiseAjax(json){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? let url = json.url
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? let type = json.type || 'get'
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? let parmas = json.data || {}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? let str = ''
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for(let k in parmas){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? str += k+'='+parmas[k]+'&'
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return new Promise((resolve.reject)=>{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? let xhr = new XMLHttpRequest()
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (type.toLowerCase()==='get'){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? xhr.open('get',`${url}?${str}time=${Data.now()}`,true)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? xhr.send()
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}else if(type.toLowerCase()==='post'{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? xhr.open('post',url,true)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? xhr.send(str.substring(0,str.lastIndexOf('&')))??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? xhr.onreadystatechange = function (){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if(this.readyState===4){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(this.status>=200 && this.status<300){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? resolve(JSON.parse(this.reponseText)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}else{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?let error = new Error()
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?error.status = this.status
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? reject(error)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ?})
? ? ? ? ? ? ? ? ? ?}
Promise的類(lèi)(高級(jí))方法
(1)promise.all()
將多個(gè)promise實(shí)例,包裝成一個(gè)新的promise實(shí)例,簡(jiǎn)單的來(lái)說(shuō)就是多個(gè)異步操作都成功則才執(zhí)行成功的回調(diào),否則執(zhí)行失敗的回調(diào)
參數(shù)說(shuō)明: 接收一個(gè)數(shù)組為參數(shù),數(shù)組的每一項(xiàng)都是promise實(shí)例
(2)promise.race()
競(jìng)賽,將多個(gè)promise實(shí)例,包裝成一個(gè)新的promise實(shí)例,只要有一個(gè)實(shí)例率先改變狀態(tài),promise的狀態(tài)就跟著改變
參數(shù)說(shuō)明: 接收一個(gè)數(shù)組作為參數(shù),數(shù)組的每一項(xiàng)都是promise實(shí)例
例如:請(qǐng)求三張網(wǎng)絡(luò)圖片有一張加載完,所有圖片完全加載完添加到頁(yè)面上
封裝加載圖片的方法
? ? ? ? ? ? function loadImg(src){
? ? ? ? ? ? ? ?return new Promise((resolve,reject)=>{
? ? ? ? ? ? ? ? ?var img = document.createElement('img')
? ? ? ? ? ? ? ? ?img.src = src
? ? ? ? ? ? ? ? ?img.onload = function(){
? ? ? ? ? ? ? ? ? resolve( img )
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? img.error = function(){
? ? ? ? ? ? ? ? ? ?reject()
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ?}
? ? ? }
? ? ? ? ? ? ? ? ? ? ?Promise.all([
? ? ? ? ? ? ? ? ? ? ? loadImg
? ? ? ? ? ? ? ? ? ? ? ('圖片路徑'),
? ? ? ? ? ? ? ? ? ? ?loading
? ? ? ? ? ? ? ? ? ? ? ?('圖片路徑')
? ? ? ? ? ? ? ? ? ?]).then(function(imgs){
? ? ? ? ? ? ? ? ? ? imgs.forEach((img)=>{
? ? ? ? ? ? ? ? ? ? document.body.appendChild(img)
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? Promise.race([
? ? ? ? ? ? ? ? ? ?loadImg
? ? ? ? ? ? ? ? ? ? ('圖片路徑')
? ? ? ? ? ? ? ? ? ?loadImg
? ? ? ? ? ? ? ? ? ?('圖片路徑')
? ? ? ? ? ?]).then(function(img){
? ? ? ? ? ? ? ? ?document.body.appendChild(img)
? ? ? ? ?}
promise缺點(diǎn)
①一旦新建就會(huì)立即執(zhí)行,無(wú)法中途取消
②如果不設(shè)置回調(diào)函數(shù),promise內(nèi)容拋出的錯(cuò)誤,不會(huì)反應(yīng)到外部
③當(dāng)處于pending狀態(tài)時(shí),無(wú)法得知目前進(jìn)展到哪一個(gè)階段
promise的鏈?zhǔn)讲僮鞔a繁多,有一個(gè)方法可以解決既簡(jiǎn)單又方便
Async:異步主要是將異步的代碼變成同步的寫(xiě)法
await等待? await? ?promise對(duì)象
await異步參數(shù)
async? function fn(){
let ret = await promiseAjax({url:'data/arr.txt'})
console.log(ret)
ret = await promiseAjax({url:'data/list/txt'})
console.log(ret)
}
fn()
需要引入jquery.js
?async function fn(){
? ? ? ? ? ? try{
? ? ? ? ? ? ? ? let ret=await new Promise((resolve,reject)=>{
? ? ? ? ? ? ? ? //....
? ? ? ? ? ? ? ? if(成功了){
? ? ? ? ? ? ? ? ? ? resolve(成功的數(shù)據(jù))
? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? reject(錯(cuò)誤的信息)
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? }.catch(e){
? ? ? ? ? ? ? ? console.log(e);
? ? ? ? ? ? }finally{
? ? ? ? ? ? ? ? //不管有沒(méi)有錯(cuò)誤這里的代碼都會(huì)執(zhí)行
? ? ? ? ? ? }
? ? ? ? }