JavaScript動態載入script方式引用百度地圖API 拓展---JavaScript的Promise

来源:https://www.cnblogs.com/yangzhengier/archive/2019/05/11/10849162.html
-Advertisement-
Play Games

上一篇博客JavaScript動態載入script方式引用百度地圖API,Uncaught ReferenceError: BMap is not defined 這篇文章中我接觸到一個新的單詞:Promise,藉此來記錄一下它,引用來源:JS - Promise使用詳解--摘抄筆記 因為現在還不會 ...


上一篇博客JavaScript動態載入script方式引用百度地圖API,Uncaught ReferenceError: BMap is not defined

這篇文章中我接觸到一個新的單詞:Promise,藉此來記錄一下它,引用來源:JS - Promise使用詳解--摘抄筆記

因為現在還不會jquery,就只看了原生js部分的內容。

一、promises相關概念

promises 的概念是由 CommonJS 小組的成員在 Promises/A 規範中提出來的。  

1,then()方法介紹

根據 Promise/A 規範,promise 是一個對象,只需要 then 這一個方法。then 方法帶有如下三個參數:
  • 成功回調
  • 失敗回調
  • 前進回調(規範沒有要求包括前進回調的實現,但是很多都實現了)。
一個全新的 promise 對象從每個 then 的調用中返回。  

2,Promise對象狀態

Promise 對象代表一個非同步操作,其不受外界影響,有三種狀態:
  • Pending(進行中、未完成的)
  • Resolved(已完成,又稱 Fulfilled)
  • Rejected(已失敗)。
(1)promise 從未完成的狀態開始,如果成功它將會是完成態,如果失敗將會是失敗態。 (2)當一個 promise 移動到完成態,所有註冊到它的成功回調將被調用,而且會將成功的結果值傳給它。另外,任何註冊到 promise 的成功回調,將會在它已經完成以後立即被調用。 (3)同樣的,當一個 promise 移動到失敗態的時候,它調用的是失敗回調而不是成功回調。 (4)對包含前進特性的實現來說,promise 在它離開未完成狀態以前的任何時刻,都可以更新它的 progress。當 progress 被更新,所有的前進回調(progress callbacks)會被傳遞以 progress 的值,並被立即調用。前進回調被以不同於成功和失敗回調的方式處理;如果你在一個 progress 更新已經發生以後註冊了一個前進回調,新的前進回調只會在它被註冊以後被已更新的 progress 調用。 (5)註意:只有非同步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。

3,Promise/A規範圖解

原文:JS - Promise使用詳解1(基本概念、使用優點)

4,目前支持Promises/A規範的庫

  • Q:可以在NodeJS 以及瀏覽器上工作,與jQuery相容,可以通過消息傳遞遠程對象。
  • RSVP.js:一個輕量級的庫,它提供了組織非同步代碼的工具。
  • when.js:體積小巧,使用方便。
  • NodeJS的Promise
  • jQuery 1.5:據說是基於“CommonJS Promises/A”規範
  • WinJS / Windows 8 / Metro
 

二、使用promises的優勢

1,解決回調地獄(Callback Hell)問題

(1)有時我們要進行一些相互間有依賴關係的非同步操作,比如有多個請求,後一個的請求需要上一次請求的返回結果。過去常規做法只能 callback 層層嵌套,但嵌套層數過多的話就會有 callback hell 問題。比如下麵代碼,可讀性和維護性都很差的。
firstAsync(function(data){
    //處理得到的 data 數據
    //....
    secondAsync(function(data2){
        //處理得到的 data2 數據
        //....
        thirdAsync(function(data3){
              //處理得到的 data3 數據
              //....
        });
    });
});

(2)如果使用 promises 的話,代碼就會變得扁平且更可讀了。前面提到 then 返回了一個 promise,因此我們可以將 then 的調用不停地串連起來。其中 then 返回的 promise 裝載了由調用返回的值。

firstAsync()
.then(function(data){
    //處理得到的 data 數據
    //....
    return secondAsync();
})
.then(function(data2){
    //處理得到的 data2 數據
    //....
    return thirdAsync();
})
.then(function(data3){
    //處理得到的 data3 數據
    //....
});

2,更好地進行錯誤捕獲 

多重嵌套 callback 除了會造成上面講的代碼縮進問題,更可怕的是可能會造成無法捕獲異常或異常捕獲不可控。
(1)比如下麵代碼我們使用 setTimeout 模擬非同步操作,在其中拋出了個異常。但由於非同步回調中,回調函數的執行棧與原函數分離開,導致外部無法抓住異常。
 
function fetch(callback) {
    setTimeout(() => {
        throw Error('請求失敗')
    }, 2000)
}
 
try {
    fetch(() => {
        console.log('請求處理') // 永遠不會執行
    })
} catch (error) {
    console.log('觸發異常', error) // 永遠不會執行
}
 
// 程式崩潰
// Uncaught Error: 請求失敗
(2)如果使用 promises 的話,通過 reject 方法把 Promise 的狀態置為 rejected,這樣我們在 then 中就能捕捉到,然後執行“失敗”情況的回調。  
function fetch(callback) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
             reject('請求失敗');
        }, 2000)
    })
}
 
 
fetch()
.then(
    function(data){
        console.log('請求處理');
        console.log(data);
    },
    function(reason, data){
        console.log('觸發異常');
        console.log(reason);
    }
);
當然我們在 catch 方法中處理 reject 回調也是可以的。
function fetch(callback) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
             reject('請求失敗');
        }, 2000)
    })
}
 
 
fetch()
.then(
    function(data){
        console.log('請求處理');
        console.log(data);
    }
)
.catch(function(reason){
    console.log('觸發異常');
    console.log(reason);
});
 

第二部分:

JS - Promise使用詳解2(ES6中的Promise)

2015年6月, ES2015(即 ECMAScript 6、ES6) 正式發佈。其中 Promise 被列為正式規範,成為 ES6 中最重要的特性之一。

1,then()方法

簡單來講,then 方法就是把原來的回調寫法分離出來,在非同步操作執行完後,用鏈式調用的方式執行回調函數。 而 Promise 的優勢就在於這個鏈式調用。我們可以在 then 方法中繼續寫 Promise 對象並返回,然後繼續調用 then 來進行回調操作。   (1)下麵通過樣例作為演示,我們定義做飯、吃飯、洗碗(cook、eat、wash)這三個方法,它們是層層依賴的關係,下一步的的操作需要使用上一部操作的結果。(這裡使用 setTimeout 模擬非同步操作)
//做飯
function cook(){
    console.log('開始做飯。');
    var p = new Promise(function(resolve, reject){        //做一些非同步操作
        setTimeout(function(){
            console.log('做飯完畢!');
            resolve('雞蛋炒飯');
        }, 1000);
    });
    return p;
}
 
//吃飯
function eat(data){
    console.log('開始吃飯:' + data);
    var p = new Promise(function(resolve, reject){        //做一些非同步操作
        setTimeout(function(){
            console.log('吃飯完畢!');
            resolve('一塊碗和一雙筷子');
        }, 2000);
    });
    return p;
}
 
function wash(data){
    console.log('開始洗碗:' + data);
    var p = new Promise(function(resolve, reject){        //做一些非同步操作
        setTimeout(function(){
            console.log('洗碗完畢!');
            resolve('乾凈的碗筷');
        }, 2000);
    });
    return p;
}

(2)使用 then 鏈式調用這三個方法:

cook()
.then(function(data){
    return eat(data);
})
.then(function(data){
    return wash(data);
})
.then(function(data){
    console.log(data);
});
當然上面代碼還可以簡化成如下:
cook()
.then(eat)
.then(wash)
.then(function(data){
    console.log(data);
});

(3)運行結果如下:

原文:JS - Promise使用詳解2(ES6中的Promise)

2,reject()方法

上面樣例我們通過 resolve 方法把 Promise 的狀態置為完成態(Resolved),這時 then 方法就能捕捉到變化,並執行“成功”情況的回調。 而 reject 方法就是把 Promise 的狀態置為已失敗(Rejected),這時 then 方法執行“失敗”情況的回調(then 方法的第二參數)。   (1)下麵同樣使用一個樣例做演示
//做飯
function cook(){
    console.log('開始做飯。');
    var p = new Promise(function(resolve, reject){        //做一些非同步操作
        setTimeout(function(){
            console.log('做飯失敗!');
            reject('燒焦的米飯');
        }, 1000);
    });
    return p;
}
 
//吃飯
function eat(data){
    console.log('開始吃飯:' + data);
    var p = new Promise(function(resolve, reject){        //做一些非同步操作
        setTimeout(function(){
            console.log('吃飯完畢!');
            resolve('一塊碗和一雙筷子');
        }, 2000);
    });
    return p;
}
 
cook()
.then(eat, function(data){
  console.log(data + '沒法吃!');
})

運行結果如下:

原文:JS - Promise使用詳解2(ES6中的Promise) (2)如果我們只要處理失敗的情況可以使用 then(null, ...),或是使用接下來要講的 catch 方法。
cook()
.then(null, function(data){
  console.log(data + '沒法吃!');
})

3,catch()方法

(1)它可以和 then 的第二個參數一樣,用來指定 reject 的回調

cook()
.then(eat)
.catch(function(data){
    console.log(data + '沒法吃!');
});
(2)它的另一個作用是,當執行 resolve 的回調(也就是上面 then 中的第一個參數)時,如果拋出異常了(代碼出錯了),那麼也不會報錯卡死 js,而是會進到這個 catch 方法中。
//做飯
function cook(){
    console.log('開始做飯。');
    var p = new Promise(function(resolve, reject){        //做一些非同步操作
        setTimeout(function(){
            console.log('做飯完畢!');
            resolve('雞蛋炒飯');
        }, 1000);
    });
    return p;
}
 
//吃飯
function eat(data){
    console.log('開始吃飯:' + data);
    var p = new Promise(function(resolve, reject){        //做一些非同步操作
        setTimeout(function(){
            console.log('吃飯完畢!');
            resolve('一塊碗和一雙筷子');
        }, 2000);
    });
    return p;
}
 
cook()
.then(function(data){
    throw new Error('米飯被打翻了!');
    eat(data);
})
.catch(function(data){
    console.log(data);
});

運行結果如下:

原文:JS - Promise使用詳解2(ES6中的Promise) 這種錯誤的捕獲是非常有用的,因為它能夠幫助我們在開發中識別代碼錯誤。比如,在一個 then() 方法內部的任意地方,我們做了一個 JSON.parse() 操作,如果 JSON 參數不合法那麼它就會拋出一個同步錯誤。用回調的話該錯誤就會被吞噬掉,但是用 promises 我們可以輕鬆的在 catch() 方法里處理掉該錯誤。   (3)還可以添加多個 catch,實現更加精準的異常捕獲。
somePromise.then(function() {
 return a();
}).catch(TypeError, function(e) {
 //If a is defined, will end up here because
 //it is a type error to reference property of undefined
}).catch(ReferenceError, function(e) {
 //Will end up here if a wasn't defined at all
}).catch(function(e) {
 //Generic catch-the rest, error wasn't TypeError nor
 //ReferenceError
}); 

4,all()方法

Promise 的 all 方法提供了並行執行非同步操作的能力,並且在所有非同步操作執行完後才執行回調。   (1)比如下麵代碼,兩個個非同步操作是並行執行的,等到它們都執行完後才會進到 then 裡面。同時 all 會把所有非同步操作的結果放進一個數組中傳給 then。
//切菜
function cutUp(){
    console.log('開始切菜。');
    var p = new Promise(function(resolve, reject){        //做一些非同步操作
        setTimeout(function(){
            console.log('切菜完畢!');
            resolve('切好的菜');
        }, 1000);
    });
    return p;
}
 
//燒水
function boil(){
    console.log('開始燒水。');
    var p = new Promise(function(resolve, reject){        //做一些非同步操作
        setTimeout(function(){
            console.log('燒水完畢!');
            resolve('燒好的水');
        }, 1000);
    });
    return p;
}
 
Promise
.all([cutUp(), boil()])
.then(function(results){
    console.log("準備工作完畢:");
    console.log(results);
});
(2)運行結果如下: 原文:JS - Promise使用詳解2(ES6中的Promise)

5,race()方法

race 按字面解釋,就是賽跑的意思。race 的用法與 all 一樣,只不過 all 是等所有非同步操作都執行完畢後才執行 then 回調。而 race 的話只要有一個非同步操作執行完畢,就立刻執行 then 回調。 註意:其它沒有執行完畢的非同步操作仍然會繼續執行,而不是停止。   (1)這裡我們將上面樣例的 all 改成 race
Promise
.race([cutUp(), boil()])
.then(function(results){
    console.log("準備工作完畢:");
    console.log(results);
});
原文:JS - Promise使用詳解2(ES6中的Promise)   (2)race 使用場景很多。比如我們可以用 race 給某個非同步請求設置超時時間,並且在超時後執行相應的操作。
//請求某個圖片資源
function requestImg(){
    var p = new Promise(function(resolve, reject){
    var img = new Image();
    img.onload = function(){
       resolve(img);
    }
    img.src = 'xxxxxx';
    });
    return p;
}
 
//延時函數,用於給請求計時
function timeout(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject('圖片請求超時');
        }, 5000);
    });
    return p;
}
 
Promise
.race([requestImg(), timeout()])
.then(function(results){
    console.log(results);
})
.catch(function(reason){
    console.log(reason);
});

上面代碼 requestImg 函數非同步請求一張圖片,timeout 函數是一個延時 5 秒的非同步操作。我們將它們一起放在 race 中賽跑。

  • 如果 5 秒內圖片請求成功那麼便進入 then 方法,執行正常的流程。
  • 如果 5 秒鐘圖片還未成功返回,那麼則進入 catch,報“圖片請求超時”的信息。
原文:JS - Promise使用詳解2(ES6中的Promise)

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、在函數調用的時候,瀏覽器每次都會傳遞進兩個隱式參數 1. 函數的上下文對象this 2. 封裝實參的對象arguments 二、arguments 對象 1. arguments 對象實際上是所在函數的一個內置類數組對象 2. 每個函數都有一個arguments屬性,表示函數的實參集合,這裡的實 ...
  • CSS學習 學習資源 http://www.csszengarden.com/ CSS語法檢查http://jigsaw.w3.org/css-validator/ 配置CSS的方法: 1.行內式 行內式通過直接設置元素的style屬性來引入css <div style="width: 100px; ...
  • 一、css寬高自適應: 1.寬度自適應: 元素寬度設為100%(塊狀元素的預設寬度為100%) 註:應用在通欄效果中 2.高度自適應: height:auto;或者不設置高度 3.最小,最大高度,最小,最大寬度: a)最小高度 min-height:value; IE6不識別min-height屬性 ...
  • 一、css佈局模型: 流動模型(Flow) 浮動模型(Float) 層模型(Layer) 1、流動模型: 頁面在沒有設置任何css樣式,元素按照本身的特性在瀏覽器中顯示,這樣的佈局模型稱為流動模型; 2、浮動模型: ①.浮動屬性 float:none(預設值,不浮動)|left(左浮動)|right ...
  • 一、html元素可分為三大類:塊元素、內聯元素、可變元素 1.塊元素: 常見塊狀元素:div,p,ul,ol,li,dl,dt,dd,form,hr,table,tr,td,h1-h6,filedset,caption 塊狀元素特點: (a)以塊的形式顯示為一個矩形區域; (b)塊狀元素獨占一行,自 ...
  • 一、列表類屬性: 1.列表符號樣式: list-style-type:disc(實心圓)|circle(空心圓)|square(實心方塊)|decimal(數字)|none(去掉列表符號樣式); 2.使用圖片作為列表符號: list-style-image:url(圖片路徑); 3.列表符號位置: ...
  • Cascading Style Sheet CSS(Cascading Style Sheet)即層疊樣式表,簡稱樣式表。要理解層疊樣式表的概念先要理解樣式的概念。樣式就是對網頁中的 元素(字體、段落、圖像、列表等)屬性的整體概括,即描述所有網頁對象的顯示形式(例如,文字的大小、字體、背景及圖像的顏 ...
  • es6新增關鍵字class,代表類,其實相當於代替了es5的構造函數 通過構造函數可以創建一個對象實例,那麼通過class也可以創建一個對象實列 es5中繼承的方式 1原型鏈繼承 2.構造函數繼承 3.組合繼承,融合了上面兩種方式 /* 組合繼承,既能達到對父類屬性的繼承,也能繼承父類原型上的方法 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...