日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

回调地狱解决方案之Promise

發布時間:2024/4/13 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 回调地狱解决方案之Promise 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為什么出現Promise

在javascript開發過程中,代碼是單線程執行的,同步操作,彼此之間不會等待,這可以說是它的優勢,但是也有它的弊端,如一些網絡操作,瀏覽器事件,文件等操作等,都必須異步執行,針對這些情況,起初的操作都是使用回調函數實現。

實現方式如下(偽代碼):

function One(callback) {if (success) {callback(err, result);} else {callback(err, null);} } 復制代碼

One(function (err, result) { //執行完One函數內的內容,成功的結果回調回來向下執行 }) 復制代碼

上述代碼只是一層級回調,如果代碼復雜后,會出現多層級的回調,代碼可讀性也會很差,那有沒有一種方式,不用考慮里面的內容,直接根據結果成功還是失敗執行下面的代碼呢?有的,Promise(承諾),在ES6中對Promise進行了同意的規范。

Promise的含義

  • 書上這么說:

    Promise 是異步編程的一種解決方案,比傳統的解決方案–回調函數和事件--更合理和更強大。它由社區最早提出和實現,ES6將其寫進了語言標準,統一了語法,原生提供了Promise

    所謂Promise ,簡單說就是一個容器,里面保存著某個未來才回結束的事件(通常是一個異步操作)的結果。從語法上說,Promise是一個對象,從它可以獲取異步操作的消息。 Promise 對象的狀態不受外界影響

  • Promise/a+ 官方網站給出的定義 A promise represents the eventual result of an asyncchronous operation

    翻譯:表示一個異步操作的最終結果。

  • 我的理解:

    Promise是回調函數可以規范鏈式調用

Promise原理與講解

原理
  • Promise的三種狀態
    • pending:進行中
    • fulfilled :執行成功
    • rejected :執行失敗

    注意Promise在某一時刻只能處于一種狀態

  • Promise的狀態改變
    • pending------》fulfilled(resolved)
    • pending------》rejected

    Promise的狀態改變,狀態只能由pending轉換為rejected或者rejected,一旦狀態改變完成后將無法改變(不可逆性)

    用代碼講原理
  • 創建一個Promise
  • 創建Promise需要用到Promise的構造函數來實現,代碼如下:

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

    if(/* 一些異步操作成功*/) { resolve(value); }else { reject(error); }

    復制代碼

    }) 復制代碼

    代碼分析:

    • 在異步操作完成之后,會針對不同的返回結果調用resolve和reject。
    • resolve和reject是兩個函數,resolve是異步操作成功時候被調用,將異步操作的返回值作為參數傳遞到外部;reject是異步操作出異常時候被調用,將錯誤信息作為參數傳遞出去。
    • ==Promise其實沒有做任何實質的代碼操作,它只是對異步操作回調函數的不同結果定義了不同狀態。==
    • resolve函數和reject函數只是把異步結果傳遞出去
  • 異步結果傳遞出去后,then來接 Promise對象將結果傳遞出來后,使用then方法來獲取異步操作的值: 代碼如下:
  • promise.then(function(value){//success

    },function(error){

    復制代碼

    }); 復制代碼

    代碼分析:

    • then方法將兩個匿名函數作為參數,接收resolve和reject這兩個函數的值。
    • value是執行成功的值,error是執行出錯時的錯誤信息。
    • 對于error錯誤異常結果出現的時候,可以不單獨寫匿名錯誤的函數,可以直接用catch拋出
    promise.then(function (data){//success }) .catch(function(error){//error }) 復制代碼
    • 注意then方法==只是==用來獲取異步操作的值。
  • then的返回值又是怎樣呢? 先看一段調用兩次then的代碼:
  • //之前創建promise操作后 promise.then(function(value){conlose.log(value); //有值 }.then(function(value) {conlose.log(value); //未定義 }); 復制代碼

    代碼分析:

    • 上面的第二個then方法中的值雖然是未定義,但是每一個then一定會==返回一個新的peomise對==象,但是默認是一個空對象。
    • 對于這個空對象我們如果想繼續做一些什么,需要進行處理,可以用非空Promise對這個空的進行賦值覆蓋,然后繼續then的鏈式調用。
    • then 中的==retuen==關鍵字很重要,聯系著下一個then的調用。
    幾個常用api
    • Promise.resolve resolve方法用來將一個非Promise對象轉化為Promise對象

    轉換的對象是一個常量或者不具備狀態的語句,轉換后的對象自動處于resolve狀態。 轉換的后的結果和原來一樣

    var promise =Promise.resolve("hello world"); promise.then(function(result){console.log(result); //輸出結果 hello world }) 復制代碼

    轉換的對象如果直接是一個異步方法,不可以這么使用。

    • Promise.all(常用api) 多個promise需要執行的時候,可以使用promise.all方法統一聲明,該方法可以將多個Promise對象包裝成一個Promise。

    代碼如下

    promise.all( //一系列promise操作 ).then(function(results){

    }).catch(function(error){

    復制代碼

    }); 復制代碼

    代碼分析:

    • promise.all對多有執行結果做一個包裝傳給了then
    • promise.all中的執行順序是怎么樣的,Promise的執行順序是從被創建開始的,也就是在調用all的時候,==所有的promise都已經開始執行==了,all方法只是等到==所有的對象都執行完成==,才會吧結果==傳遞給then==。
    • all中的promise,如果有一個狀態變成了reject那么轉換后的Promise字節變成reject,錯誤信息傳遞哥catch,不會傳遞給then。(但是并不是說all這里面剛開始執行成功的操作就不算數了)

    Promise在開發中的應用

    項目開發中promise的應用代碼:

    Promise.all([self.count({phoneNumber: mobile, createdOn: {$gt: hour}}),self.count({ip: ip, createdOn: {$gt: hour}})]).then(function (results) {if (results[0] >= 5) {return callback({code: -1, message: '短信發送頻率過快,每手機號1小時內只能發送5次'});}if (results[1] >= 5) {return callback({code: -1, message: '短信發送頻率過快,每IP1小時內只能發送5次'});}let code = {phoneNumber: mobile,code: tool.makeRandomStr(4, 1).toLowerCase(),createdOn: new Date(),expiredOn: new Date(new Date().getTime() + (20 * 60 * 1000)), //20分鐘失效ip: ip,isUsed: false};self.create(code, function (err, newCode) {if (newCode) {sms.sendSMS(mobile, newCode.code, 'ali', function (err, body) {console.log(body);if (err)console.log("短信驗證碼發送失敗:", err);});callback({code: 0, message: "驗證碼已經發送"});} else {callback({code: -1, message: "驗證碼發送失敗,請重試"});}})}) 復制代碼

    項目開發過程中使用promise.all的代碼,當時是為了實現短信驗證碼發送前的校驗功能。 all中的兩個promise,第一個是統計時間內該手機號發送驗證碼數量;第二個是統計時間內該ip發送驗證碼的數量。

    Promise使用過程中注意事項與誤區

    注意事項在上面原理講解過程中,基本都提到過,只是重要的事情多說兩遍。

    • 狀態不可逆性
    • resolve函數和reject函數只是傳遞異步結果
    • then進行層級調用的時候,每次的返回值都一個空promise對象,如果想繼續使用,賦值替換掉空promise對象,但是返回的時候return關鍵字很重要,不要忘了。
    • promise.all中的執行順序是并行的,但是會等全部完成的結果傳遞給then
    • ==執行順序==,promise是then方法調用之后才會執行嗎?還是從創建那一刻就開始執行? promise從創建那一刻就開始執行,只是把結果傳遞給了then,then與promise的執行無關。

    Promise的反思

    Promise的講解就到這里,但是大家在開發過程中,會發現有些時候多次操作異步會出現很多層級的調用,也就是

    promise.then(...)

    .then(...)

    復制代碼

    .then(...) 復制代碼

    這種情況,代碼雖然看起來會比callback的回調簡介和規范了很多,但是還是感覺一些復雜,有沒有更好的解決辦法呢?請看下一篇博客

    回調的終極使用--async和await的講解

    覺得本文對你有幫助?請分享給更多人 我的公眾號.jpg

    歡迎大家關注我的公眾號——程序員成長指北。請自行微信搜索——“程序員成長指北”

    總結

    以上是生活随笔為你收集整理的回调地狱解决方案之Promise的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。