Promise 真的懂了嗎胶逢?

(1) var

  • var在函數(shù)外定義,是全局變量饰潜,函數(shù)內(nèi)可以使用
  • var在函數(shù)內(nèi)定義初坠,是局部變量,函數(shù)外不能使用
  • var 在其他代碼塊中定義彭雾,是全局變量 ----- 如 if 等
var x = 10;

( 
  function fun() {
     var y = 20;
     console.log(x)      // 10
  } 
)();

console.log(y)    // 報錯 y is not defined     ----- var在函數(shù)內(nèi)部定義某筐,是局部變量,函數(shù)外無法讀取



-------------------------------------

if (true) {
    var z = 300;
}
console.log(z)    // 300       // var在其他代碼塊中定義冠跷,是全局變量


(2) 對象es6

  • 表達式 - 可以作為對象的屬性名和方法名
  • 變量名可以直接作為對象屬性名
  • 對象中的方法可以簡寫
let ani = 'animal'
let nam = 'name'


let newAr = {
   ani // 變量名直接作為對象的屬性名,等同于 ( ani: ani 即 ani: animal) 前者是字符串身诺,后者ani是變量
   nam,
   [ani + nam] : 2000,   // 中括號中寫表達式蜜托,作為對象的屬性名或方法名
   getAge() {            // 方法名簡寫,相當于 getAge: funciton() { console.log(this.animalname) }
      console.log(this.animalname)
   }
}


newAr.getAge();
console.log(newAr,'newAr')









Promise

Promise含義

  • promise是一種異步編程的解決方案
  • 比傳統(tǒng)的 回調(diào)函數(shù)和事件 更強大

Promise具體是什么霉赡?

  • promise是一個容器橄务,里面保存著某個未來才會結(jié)束的事件 (比如 異步操作的結(jié)果)
  • 語法上:promise是一個對象,可以從它獲取異步操作的消息
  • promise提供統(tǒng)一的api穴亏,所以各種異步操作都可以用同樣的方法進行處理

Promise對象的特點蜂挪?

  • promise對象的狀態(tài)不受外界影響 ----- ( promise有三種狀態(tài) )
    pending進行中,fulfilled已成功嗓化,rejected已失敗
    只有異步操作的結(jié)果可以決定當前是哪一種狀態(tài)棠涮,其他別的操作無法改變這個狀態(tài)
  • promise的狀態(tài)一旦改變,就不會再變刺覆,任何時候都能得到這個結(jié)果
    promise狀態(tài)改變只有兩種情況: pending狀態(tài) 變?yōu)?fulfilled狀態(tài)pending狀態(tài) 變?yōu)?rejected狀態(tài)
    只要這兩種情況發(fā)生严肪,狀態(tài)就凝固了,不會再改變谦屑,稱為 ( resolved ) 已定型
    例如:只要改變已經(jīng)發(fā)生了驳糯,你再對promise對象添加回調(diào)函數(shù),也會立即得到這個結(jié)果

Promise vs 事件氢橙?

Promise:只要改變已經(jīng)發(fā)生了酝枢,你再對promise對象添加回調(diào)函數(shù),也會立即得到這個結(jié)果
event----: 如果改變發(fā)生了悍手,你再去監(jiān)聽帘睦,得不到結(jié)果

Promise對象 的優(yōu)缺點袍患?

  • 優(yōu)點
    promise對象,可以將 異步操作同步操作的流程 表達出來官脓,避免層層嵌套
  • 缺點
    (1) promise一旦新建协怒,就會立即執(zhí)行,無法取消
    (2) 如果不設(shè)置回掉函數(shù)卑笨,promise內(nèi)部拋出的錯誤就不會反應(yīng)到外部
    (3) 處于pending狀態(tài)時孕暇,是不能知道目前進展到哪個階段的 ( 剛開始?赤兴,即將結(jié)束妖滔?)

Promise構(gòu)造函數(shù)

es6規(guī)定,Promise對象 是一個構(gòu)造函數(shù)桶良,用來生成Promise實例

  • Promise構(gòu)造函數(shù)座舍,接受一個函數(shù)作為參數(shù),該函數(shù)有兩個參數(shù)分別是 resolve 和
    reject陨帆,它們是兩個函數(shù)
  • resolve 和 reject 由 javascript 引擎提供曲秉,不用自己部署
  • resolve函數(shù)
    resolve函數(shù)的作用是,將Promise對象的狀態(tài)疲牵,由pending=>變?yōu)閒ulfilled承二,在異步操作成功時調(diào)用笛臣,并將異步操作的結(jié)果砌滞,作為參數(shù)傳遞出去
  • reject函數(shù)
    reject函數(shù)的作用是春霍,將Promise對象的狀態(tài)辞色,由pending=>變?yōu)閞ejected刑赶,在異步操作失敗時調(diào)用箕憾,并將異步操作報出的錯誤袍辞,作為參數(shù)傳遞出去

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 異步操作成功 */){
    ... 異步操作
    resolve(value);  //  異步操作的結(jié)果作為參數(shù)浆兰,傳遞出去
  } else {
    reject(error);
  }
});

  • .then 方法
    (1) promise實例生成以后颓哮,可以用.then方法家妆,分別指定resolved狀態(tài) 和 rejected狀態(tài)的回調(diào)函數(shù)
    (2) .then方法可以接受 ( 兩個回調(diào)函數(shù) ) 作為參數(shù)冕茅,
    ===> 第一個回調(diào)函數(shù),在promise對象的狀態(tài)變?yōu)?resolved時調(diào)用 ------ (該回調(diào)函數(shù)在promise構(gòu)造函數(shù)中定義嵌赠,在實例化后,.then方法中調(diào)用 )
    ===> 第二個回調(diào)函數(shù)姜挺,在promise對象的狀態(tài)變?yōu)?rejected 時調(diào)用 ------ (該回調(diào)函數(shù)在promise構(gòu)造函數(shù)中定義,在實例化后凌箕,.then方法中調(diào)用 )
    (3) 第二個回調(diào)是可選的拧篮,可以不提供
    (4) 這兩個函數(shù)串绩,都接受 promise對象 傳出的值 作為參數(shù)

promise.then(function(value) {   

  // success
  // 該回調(diào)函數(shù)在promise對象狀態(tài)變?yōu)閞esolved時調(diào)用,參數(shù)是promise對象 resolved時礁凡,傳出的值

}, function(error) {
  // failure
});

很重要的一個例子

//很重要的一個例子


function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
  });
}

timeout(100).then((value) => {
  console.log(value);
});


上面代碼中慧妄,timeout方法返回一個Promise實例,表示一段時間以后才會發(fā)生的結(jié)果塞淹。

過了指定的時間(ms參數(shù))以后窟蓝,Promise實例的狀態(tài)變?yōu)閞esolved,就會觸發(fā)then方法綁定的回調(diào)函數(shù)饱普。

promise新建后會立即執(zhí)行

// promise新建后會立即執(zhí)行



let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();  // 這里沒有傳參运挫,作用是去觸發(fā).then中的回調(diào)函數(shù)

     // resovle()函數(shù)的作用,是把promise實例對象的狀態(tài)變?yōu)閞esolved套耕,  --------
     // 在異步操作成功時調(diào)用滑臊,并將異步操作的結(jié)果作為參數(shù)傳遞出去

     // 而當promise實例對象的狀態(tài)變?yōu)?resolved時,就會觸發(fā) .then函數(shù)中的 回調(diào)函數(shù)   --------
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');

// Promise                   // 注意執(zhí)行順序
// Hi!
// resolved



上面代碼中箍铲,Promise 新建后立即執(zhí)行,所以首先輸出的是Promise鬓椭。

然后颠猴,then方法指定的回調(diào)函數(shù),將在當前腳本所有同步任務(wù)執(zhí)行完才會執(zhí)行小染,所以resolved最后輸出翘瓮。

( 請求圖片 ) https://blog.csdn.net/h1534589653/article/details/77528367
( Image對象 ) https://blog.csdn.net/baihuaxiu123/article/details/53091105

異步加載圖片

  componentDidMount() {
        
        function loadImage(url) {
            return new Promise((resolve, reject) => {
                const image = new Image('400', '200')   // 生成image實例對象,寬高
                image.onload = () => {
                    resolve(image)               // 加載成功時候裤翩,返回image對象
                }
                image.onerror = () => {
                    reject( new Error(`could not load image at ${url}`))   // 加載失敗是報錯
                }
                image.src = url   // 請求的圖片地址
            })
        }


        loadImage('http://pic.7y7.com/201410/2014102458431393_600x0.jpg')
            .then(res => {
                console.log( res.src )   // 拿到image對象的src 屬性
                this.setState({
                    images: res
                },() => {console.log(this.state.images)})
            },  () => {
                    // rejected狀態(tài)下的回掉函數(shù)
            })
            
    } 

resolve函數(shù)资盅,reject函數(shù) ------------- (重要)

  • 如果調(diào)用resolve和reject函數(shù)時,帶有參數(shù)踊赠,那么他們的參數(shù)會傳給回調(diào)函數(shù)
  • reject函數(shù) 的 參數(shù)呵扛, 通常是 Error對象的實例,表示拋出的錯誤
  • resolve函數(shù)的參數(shù)筐带,除了正常值以外今穿,還可能是另一個promise實例

const p1 = new Promise(function (resolve, reject) {
  // ...
});

const p2 = new Promise(function (resolve, reject) {
  // ...
  resolve(p1);       // p2異步操作的結(jié)果返回 --> p1 異步操作
})


上面代碼中,p1和p2都是 Promise 的實例伦籍,

但是p2的resolve方法將p1作為參數(shù)蓝晒,即一個異步操作的結(jié)果是返回另一個異步操作腮出。



----------------------------------------------------


注意: 上面例子中

p1的狀態(tài)決定了p2的狀態(tài)

(1) 如果 p1 的狀態(tài)是pending,那么 p2 的回調(diào)函數(shù)就會等待 p1 的狀態(tài)改變
(2) 如果 p1 的狀態(tài)是 fulfilled或者rejected胚嘲,那么 p2 的回調(diào)函數(shù)將會立即執(zhí)行

Promise嵌套 ---------------------------(重要)(重要)(重要)



componentDidMount() {
        let i = 0
        setInterval(() => {
            console.log(`經(jīng)過了${++i}s`)
        },1000)

        const p1 = new Promise( (resolve,reject) => {
            setTimeout(() => {
                reject(new Error('fail'))
                console.log('3s')  // console.log語句仍然會執(zhí)行馋劈,并且在reject()異步函數(shù) 前執(zhí)行
            },3000)
        })
        const p2 = new Promise( (resolve,reject) => {
            setTimeout( () => {
                return resolve(p1)   // 一般都在這里加return侣滩,這樣后面的代碼就不會執(zhí)行君珠,防止意外2咛怼毫缆!
                console.log('1s')
            }, 1000 )
        })

        p2.then(res => console.log(res))    // 并沒有執(zhí)行
          .catch(error => console.log(error))

    // 注意: p2.then(res => console.log(....))并沒有執(zhí)行苦丁,因為p2的狀態(tài)變成了p1的狀態(tài)旺拉,是rejected
    // p2.then(res => console.log(res,'fulfilled'), res => console.log(res,'rejected'))
    // 實際執(zhí)行的是上面的 第二個回調(diào)函數(shù)
}


解析:
(1) p1 是一個promise對象蛾狗,3s后狀態(tài)變?yōu)閞ejected
(2) p2 是一個promise對象,狀態(tài)在 1s 后改變谢鹊,但是P2的resolvef方法返回的是p1佃扼,p1是promise對象

               導(dǎo)致p2的狀態(tài)由p1決定松嘶,即 p1的狀態(tài)傳遞給p2

(3) P2會等待P1的狀態(tài)改變?yōu)?fulfilled或者reject翠订,P1狀態(tài)改變后,P2的回調(diào)函數(shù)會立刻執(zhí)行 ( --!!!重要!!!-- )

               ( 所以1s的時候官撼,.then方法并沒有輸出內(nèi)容 )
      (并且3s后似谁,p2的狀態(tài)不是fulfilled巩踏,而是 rejeced,即是p1的狀態(tài) )

(4) 又過了2s菠净,p1的狀態(tài)變?yōu)?rejected毅往,導(dǎo)致觸發(fā) .catch 回調(diào)函數(shù)


  • 一般來說攀唯,調(diào)用resolve或reject以后侯嘀,Promise 的使命就完成了谱轨,后繼操作應(yīng)該放到then方法里面碟嘴,而不應(yīng)該直接寫在resolve或reject的后面娜扇。所以雀瓢,最好在它們前面加上return語句刃麸,這樣就不會有意外司浪。

Promise.prototype.then() 方法

promise實例有.then方法,是定義在原型對象 Promise.prototype 上的

  • then() 方法的作用是為 promise實例添加狀態(tài)改變后的回調(diào)函數(shù)
  • then() 方法的參數(shù)是兩個回掉函數(shù)吁伺,第一個是 resolved 狀態(tài)的回調(diào)函數(shù)篮奄,第二個是rejected狀態(tài)的回調(diào)函數(shù) ( 第二個參數(shù)可選窟却,一般都不用,而用 catch()方法捕獲錯誤 )
  • then() 方法返回的是新的promise實例菩帝,因此可以采用鏈式寫法

Promise.prototype.then()方法的鏈式調(diào)用---------(重要)

采用鏈式的then胁附,可以指定一組按照次序調(diào)用的回調(diào)函數(shù)控妻。

  • 這時弓候,前一個回調(diào)函數(shù)他匪,有可能返回的還是一個Promise對象(即有異步操作)邦蜜,這時后一個回調(diào)函數(shù)悼沈,就會等待該Promise對象的狀態(tài)發(fā)生變化,才會被調(diào)用衣吠。


componentDidMount() {
        let i = 0
        setInterval(() => {
            console.log(`經(jīng)過了${++i}s`)
        },1000)
    
        const lian1 = new Promise( (resolve,reject) => {
            return setTimeout(() => {
                resolve('2s的promise的fulfilled狀態(tài)返回值')
            },2000)
        })
        lian1
        .then(res => console.log(res))
        .then( res => {
            return new Promise( (resolve,reject) => {
                return  setTimeout(() => {
                    return reject('3s的promise的rejected狀態(tài)返回值')
                },1000)
            })
        })
        .then(res => console.log(res,'reject'), res => console.log(res, 'reject'))
}

//  經(jīng)過了1s
//  經(jīng)過了2s
//  2s的promise的fulfilled狀態(tài)返回值
//  經(jīng)過了3s
//  3s的promise的fulfilled狀態(tài)返回值 reject
// 經(jīng)過了4s

Promise.prototype.catch()

Promise.prototype.catch() 是 .then(null, rejection) 的別名缚俏,用于指定發(fā)生錯誤時的回調(diào)函數(shù)

  • 如果promise實例對象的狀態(tài)變?yōu)閞ejected恬惯,就會觸發(fā) catch() 方法指定的回調(diào)函數(shù)
  • 如果 .then() 方法指定的回調(diào)函數(shù)在運行中拋出錯誤宿崭,也會被 catch() 方法捕獲
  • promise對象的錯誤具有冒泡性質(zhì)才写,會一直向后傳遞赞草,直到被捕獲為止
    ( 也就是說錯誤總是會被下一個catch語句捕獲 )
  • 一般來說厨疙,不要在.then()方法中定義rejected狀態(tài)的回調(diào)函數(shù),而總是使用 .catch()方法
  • 一般總是建議梗醇,promise對象后要跟 catch()方法叙谨,這樣可以處理 promise內(nèi)部發(fā)生法的錯誤手负,catch() 方法返回的還是promise對象竟终,因此后面還可以接著調(diào)用 then() 方法
  • catch() 方法中還能再拋錯誤统捶,如果 catch()方法拋出錯誤后柄粹,后面沒有catch()方法镰惦,錯誤就不會被捕獲旺入,也不會傳遞到外層。如果catch()方法拋出錯誤后礼华,后面有then()方法圣絮,會照常執(zhí)行扮匠,后面有catch()方法棒搜,錯誤還會被再一次捕獲

p.then((val) => console.log('fulfilled:', val))
 .catch((err) => console.log('rejected', err));

// 等同于

p.then((val) => console.log('fulfilled:', val))
 .then(null, (err) => console.log("rejected:", err));

例子


getJSON('/post/1.json')
  .then(function(post) {
      return getJSON(post.commentURL);
      }) 
  .then(function(comments) {
      // some code
    })
  .catch(function(error) {
      // 處理前面三個Promise產(chǎn)生的錯誤
});


上面代碼中力麸,一共有三個 Promise 對象:一個由getJSON產(chǎn)生克蚂,兩個由then產(chǎn)生埃叭。

它們之中任何一個拋出的錯誤游盲,都會被最后一個catch捕獲益缎。

promise.prototype.finally()

promise.prototype.finally()方法用于指定不管promise對象最后的狀態(tài)如何莺奔,都會執(zhí)行的操作

  • finally() 方法的回調(diào)函數(shù)令哟,不接受任何參數(shù)妨蛹。
    ( 這就意味著蛙卤,無法知道前面pormise實例對象最后的狀態(tài)是fulfilled還是rejected噩死,也就是說已维,finally()函數(shù)中的操作與狀態(tài)無關(guān)垛耳,不依賴promise對象執(zhí)行的結(jié)果 )
  • finally總是會返回之前的值

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});



上面代碼中堂鲜,不管promise最后的狀態(tài)泡嘴,在執(zhí)行完then或catch指定的回調(diào)函數(shù)以后酌予,

都會執(zhí)行finally方法指定的回調(diào)函數(shù)抛虫。

Promise.all() -------- 注意建椰,不在原型對象上

Promise.all() 方法用于將多個promise實例棉姐,包裝成一個新的promise實例

  • promise.all() 方法的參數(shù)可以不是數(shù)組伞矩,但是必須具有 iterator 接口乃坤,且返回的每個成員都是promise實例 ( 具有iterator接口湿诊,就是可遍歷的數(shù)據(jù)結(jié)構(gòu)厅须,可以被 for...of 遍歷 )
  • 注意:如果作為參數(shù)的promise實例 ( 即Promise.all()實例子是rejected狀態(tài) )自己定義了catch()方法朗和,就不會觸發(fā)Promise.all()實例的 catch() 方法

const p = Promise.all( [p1, p2, p3] );


上面代碼中例隆,promise.all()方法镀层,接受一個數(shù)組作為參數(shù)唱逢,p1, p2, p3都是promise實例

promise.all() 方法的參數(shù)可以不是數(shù)組屋休,但是必須具有 iterator 接口


p的狀態(tài)由 p1, p2, p3決定,分兩種情況

(1) 只有p1,p2,p3的狀態(tài)都變?yōu)?fulfilled痪枫, p的狀態(tài)才會變?yōu)?fulfilled
    此時,p1,p2,p3的返回值組成一個數(shù)組吃粒,傳遞給p的回調(diào)函數(shù)

(2) 只要p1,p2,p3中有一個被 rejected徐勃,p的狀態(tài)就變成rejected
    此時僻肖,第一個被rejected的實例的返回值檐涝,會傳給p的回調(diào)函數(shù)

例子

情況1:

// a,b,c都是promise實例對象
// 當a,b,c都是fulfilled狀態(tài)時谁榜, p 才是fulfilled狀態(tài)窃植,才會觸發(fā)then的resolved狀態(tài)的回調(diào)函數(shù)
// p 的回調(diào)函數(shù)的參數(shù),是a,b,c都變?yōu)閞esolved狀態(tài)時的返回值組成的數(shù)組

componentDidMount() {
        let a = new Promise((resolve, reject) => {
            return resolve(1)
        })
        let b = new Promise((resolve,reject) => {
            return resolve(2)
        })
        let c = new Promise((resolve,reject) => {
            return resolve(3)
        })

        const p = Promise.all([a,b,c])     // a,b,c都是promise實例對象

        p.then(res => console.log(res))  // 輸出 [1, 2, 3]
}
情況2:

// a,b,c都是promise實例對象
// 當a,b,c中有一個是rejected狀態(tài)時荐糜,p的狀態(tài)就是rejected狀態(tài)巷怜,
// p 的回調(diào)函數(shù)的參數(shù)葛超,是最先被rejected的Promse實例的返回值

componentDidMount() {
        let a = new Promise((resolve, reject) => {
            // return resolve(1)
            return reject(new Error('錯誤來自promise----a'))
        })
        let b = new Promise((resolve,reject) => {
            // return resolve(2)
            return reject(new Error('錯誤來自promise----b'))
        })
        let c = new Promise((resolve,reject) => {
            return resolve(3)
        })

        const p = Promise.all([a,b,c])  // p是rejected時,p的回調(diào)函數(shù)的參數(shù)是最先rejected的實例返回值

        p.then(res => console.log(res))
         .catch(err => console.log(err))  // 輸出    Error: 錯誤來自promise----a
}

特殊情況


const p1 = new Promise((resolve, reject) => {
  resolve('hello');
})
.then(result => result)
.catch(e => e);

const p2 = new Promise((resolve, reject) => {
  throw new Error('報錯了');
})
.then(result => result)
.catch(e => e);

Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 報錯了]



上面代碼中延塑,p1會resolved绣张,p2首先會rejected,

但是p2有自己的catch方法关带,該方法返回的是一個新的 Promise 實例侥涵,p2指向的實際上是這個實例嗦明。

該實例執(zhí)行完catch方法后,也會變成resolved裙戏,導(dǎo)致Promise.all()方法參數(shù)里面的兩個實例都會resolved壹罚,

因此會調(diào)用then方法指定的回調(diào)函數(shù)绪穆,而不會調(diào)用catch方法指定的回調(diào)函數(shù)。

Promise.race() --------- 對比Promise.all()

Promise.race()方法的作用同樣是將多個promise對象實例包裝成新的promise實例

  • race是賽跑,率先的意思
  • 規(guī)則: 如果p1, p2, p3 中實例對象的狀態(tài)有一個率先改變键袱, p的狀態(tài)就會跟這改變 ( 無論是變?yōu)閒ulfilled狀態(tài)付鹿,還是變?yōu)?rejected狀態(tài) )纽匙,p的回調(diào)函數(shù)的參數(shù),是最先改變的那個promise實例的返回值

const p = Promise.race([       // Promise.race() 只要有一個參數(shù)狀態(tài)改變,p的狀態(tài)就是跟著改變
  fetch('/resource-that-may-take-a-while'),    // fetch返回的是promise對象
  new Promise(function (resolve, reject) {     // 5s后變?yōu)閞ejected狀態(tài)
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
]);

p
.then(console.log)
.catch(console.error);



解析:
fetch在5s鐘內(nèi)請求成功,p變成fulfilled狀態(tài),觸發(fā)p的then()方法

fetch在5s中內(nèi)請求失敗,p變?yōu)閞ejected狀態(tài)碌尔,觸發(fā)p的catch()方法

Promise.resolve()

promise.resolve()可以將對象轉(zhuǎn)換為promise對象

  • promise.resolve('foo') 等價于 new Promise(resolve => resolve('foo'))

Promise.resolve('foo')
// 等價于
new Promise(resolve => resolve('foo'))

Promise.resolve()方法的 參數(shù)

總結(jié):
Promise.resolve()的參數(shù)無論是什么類型 ( 或者不帶參數(shù)颈走,或者參數(shù)本來就是一個promise對象,或者參數(shù)是一個thenable對象,或者參數(shù)是原始值而柑,或者參數(shù)是普通對象 )本質(zhì)上Promise.resolve()都會把參數(shù)轉(zhuǎn)化為Promise對象,只是狀態(tài)分情況而已妙同,比如:如果參數(shù)是thenable對象芒涡,會立即執(zhí)行thenable對象的then方法依啰,狀態(tài)當然后then方法中的函數(shù)決定速警,從而決定Promise.resolve()返回的promise對象的狀態(tài)
Promise.resolve()方法的參數(shù)分為四種情況

  • 參數(shù)是一個promise實例對象
    如果Promise.resolve()方法的參數(shù)是一個( 實例對象 ),那么Promise.resolve()方法將原封不動的( 返回這個實例對象 )

componentDidMount() {
        const foo = new Promise( (resolve, reject) => {
            return resolve('foo是一個promise實例對象')
        })
        const p = Promise.resolve(foo)     // Promise.resolve()的參數(shù)是一個promise實例
        console.log( p );    

    // 輸出: Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "foo是一個promise實例對象"}

}

  • 參數(shù)是一個thenable 對象
    如果Promise.resolve()方法的參數(shù)是 ( thenable對象 ),那么Promise.resolve()方法會將這個對象轉(zhuǎn)化為promise對象双妨,然后立刻執(zhí)行 thenable對象的 then 方法
什么是 thenable 對象 挑随?

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

// 如果Promise.resolve()的參數(shù)是 thenable對象, Promise.resolve()方法會把thenable對象轉(zhuǎn)化為promise對象
// 然后立刻執(zhí)行thenable對象的then方法


componentDidMount() {
        const thenable = {    // thenable對象,里面有then方法
            then: (resolve,reject) => resolve('這是thenable對象')
        }
        Promise.resolve(thenable)   // 參數(shù)是thenable對象疚察,立刻執(zhí)行thenable對象的then方法
            .then(res => console.log(res))  // thenable對象的的狀態(tài)是fulfilled,輸出其返回值
}

// 輸出:這是thenable對象
  • 參數(shù)不是thenable對象,或者根本不是一個對象
    如果參數(shù)是一個原始類型的值( 數(shù)字堤撵,字符串,布爾值 ),或者是一個不具有then方法的對象,則Promise.resolve()方法返回一個新的promise對象,狀態(tài)是fulfilled

 componentDidMount() {
    const str = 'abc'    
    const foo = Promise.resolve(str)
    // 參數(shù)是原始類型的值吉挣,Promise.resolve()方法會返回一個promise對象氯哮,狀態(tài)是resolved
            
    foo.then(res => console.log(res)) // 所以該回調(diào)會執(zhí)行
}
  • 不帶參數(shù)
    當Promise.resolve()方法不帶參數(shù)是出牧,直接返回一個promise對象,狀態(tài)是resolved

Promise.reject()方法

Promise.reject()方法返回一個promise實例對象,狀態(tài)是rejected

  • 和Promise.resolve()類似想暗,只是Promise.rejected()方法的狀態(tài)一定是rejected

const p = Promise.reject('出錯了');
p.then(null, function (s) {
  console.log(s)
});
// 出錯了


// 等同于


const p = new Promise((resolve, reject) => reject('出錯了'))
p.then(null, function (s) {
  console.log(s)
});
// 出錯了

promise對象的應(yīng)用

Promise.try()


const f = () => console.log('now');   // 函數(shù)f是一個同步事件
Promise.resolve().then(f);   // 通過Promise.resolve()返回一個promise對象捣郊,狀態(tài)是resolved僧凤,f變成異步
console.log('next'); 

// next       所以會先輸出next躯保,再輸出now
// now

如何讓同步函數(shù)同步執(zhí)行义图,異步函數(shù)異步執(zhí)行历筝,并且讓他們具有統(tǒng)一的api呢蜘渣?
  • (1) 使用async函數(shù)

await 操作符用于等待一個 Promise 對象, 它只能在異步函數(shù) async function 內(nèi)部使用.


componentDidMount() {
        const funSync1 = () => console.log('我是同步函數(shù)1111111')
        const funSync2 = () => console.log('我是同步函數(shù)2222222')

        const funAsync = async () => {     // async關(guān)鍵字蔫缸,定義的函數(shù)是異步函數(shù),返回promise對象
            await funSync1()
        }
        funAsync().then(funSync2())
        console.log('bbbb')
}

// 先把兩個同步函數(shù)變成了異步际起,在異步函數(shù)中拾碌,先執(zhí)行funSync1,后執(zhí)行funSync2
// 使用async關(guān)鍵字后街望,會把同步包裝成的異步函數(shù)校翔,按同步方式執(zhí)行
// 所以最后得到的輸出順序是:


// 我是同步函數(shù)1111111
// 我是同步函數(shù)2222222
// bbbb
  • (2) 使用 new Promise()


const f = () => console.log('now');
(
  () => new Promise(
    resolve => resolve(f())
  )
)();
console.log('next');

// now
// next

  • (3) Promise.try() 提案


const f = () => console.log('now');
Promise.try(f);
console.log('next');

// now
// next

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市灾前,隨后出現(xiàn)的幾起案子防症,更是在濱河造成了極大的恐慌,老刑警劉巖哎甲,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔫敲,死亡現(xiàn)場離奇詭異,居然都是意外死亡炭玫,警方通過查閱死者的電腦和手機奈嘿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吞加,“玉大人裙犹,你說我怎么就攤上這事酝惧。” “怎么了伯诬?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵晚唇,是天一觀的道長。 經(jīng)常有香客問我盗似,道長哩陕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任赫舒,我火速辦了婚禮悍及,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘接癌。我一直安慰自己心赶,他們只是感情好,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布缺猛。 她就那樣靜靜地躺著缨叫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荔燎。 梳的紋絲不亂的頭發(fā)上耻姥,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機與錄音有咨,去河邊找鬼琐簇。 笑死,一個胖子當著我的面吹牛座享,可吹牛的內(nèi)容都是我干的婉商。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼渣叛,長吁一口氣:“原來是場噩夢啊……” “哼丈秩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起诗箍,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤癣籽,失蹤者是張志新(化名)和其女友劉穎挽唉,沒想到半個月后滤祖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡瓶籽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年匠童,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片塑顺。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡汤求,死狀恐怖俏险,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扬绪,我是刑警寧澤竖独,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站挤牛,受9級特大地震影響莹痢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜墓赴,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一竞膳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诫硕,春花似錦坦辟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至藕届,卻和暖如春挠日,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背翰舌。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工嚣潜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人椅贱。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓懂算,卻偏偏與公主長得像,于是被迫代替她去往敵國和親庇麦。 傳聞我的和親對象是個殘疾皇子计技,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內(nèi)容