angular中的$q.defer()服務非同步處理

来源:http://www.cnblogs.com/puyongsong/archive/2016/10/28/6009041.html
-Advertisement-
Play Games

jquery和angular都有defer服務,我暫以angular為例談談我的理解,最後並附上jquery的阮一峰總結的defer。 以我目前項目的部分代碼為例說明為什麼要用deferred。 就這段代碼,我想要在位置二處使用base64,然後結果呢? 兩處位置都列印了,位置一得到base64,o ...


  jquery和angular都有defer服務,我暫以angular為例談談我的理解,最後並附上jquery的阮一峰總結的defer。

  以我目前項目的部分代碼為例說明為什麼要用deferred。

function getBase64(img){//傳入圖片路徑,返回base64
           function getBase64Image(img,width,height) {
               var canvas = document.createElement("canvas");
               canvas.width = width ? width : img.width;
               canvas.height = height ? height : img.height;

               var ctx = canvas.getContext("2d");
               ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
               var dataURL = canvas.toDataURL();
               return dataURL;
           }
           var image = new Image();
           image.crossOrigin = '';
           image.src = img;

           var base64='';
           if(img){
               image.onload =function (){
                   base64=getBase64Image(image);
                   console.log(base64);//位置一
               }
               console.log(base64);//位置二
           }
       }

  就這段代碼,我想要在位置二處使用base64,然後結果呢?

  兩處位置都列印了,位置一得到base64,ok,沒問題。當我在位置二想使用base64時,問題來了?onload隊列的問題,位置二總是無法正確的獲取到想要的base64,這個時候就可以考慮非同步問題了。

  我相信大家應該和我一樣,遇到這種情況第一反應應該是deferred讓函數非同步執行。

  那麼,我講以上代碼使用deferred之後,問題完美解決!

function getBase64(img){//傳入圖片路徑,返回base64
                function getBase64Image(img,width,height) {
                  var canvas = document.createElement("canvas");
                  canvas.width = width ? width : img.width;
                  canvas.height = height ? height : img.height;
                  var ctx = canvas.getContext("2d");
                  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
                  var dataURL = canvas.toDataURL();
                  return dataURL;
                }
                var image = new Image();
                image.crossOrigin = '';
                image.src = img;

                var deferred=$q.defer();
                if(img){
                  image.onload =function (){
                    deferred.resolve(getBase64Image(image));
                  }
                  return deferred.promise;
                }
              }

getBase64('https://img.alicdn.com/bao/uploaded/TB1qimQIpXXXXXbXFXXSutbFXXX.jpg')
               .then(function(base64){
                   var binaryblob = function (s, type) {//blob對象
                       var byteString = atob(s);
                       var array = [];
                       for (var i = 0; i < byteString.length; i++) {
                           array.push(byteString.charCodeAt(i));
                       }
                       return  new Blob([new Int8Array(array)], {type: type});
                   };
                   var binaryPictureBlob = function (dataUrl, filterHead) {//上傳base64去頭
                       var s = filterHead ? dataUrl.replace(/^data:image\/(png|jpeg|pjpeg|bmp|gif|x-png);base64,/, "") : dataUrl;
                       return binaryblob(s, "image/jpeg");
                   };
                   var pic=binaryPictureBlob(base64,true);//blob對象
                   //然後調介面將blob對象上傳
               });

這裡有上傳功能我以前的博客有介紹,可以點擊這裡去看看,給點建議!

  問題解決了,我又想到了分享!那麼我將我的拙見寫出來,請不吝賜教!

  什麼是defer?

  • $q是Angular的一種內置服務,它可以使你非同步地執行函數,並且當函數執行完成時或異常時它允許你使用函數的返回值或返回執行狀態通知等。
  • defer的意思是延遲,$q.defer() 可以創建一個deferred延遲對象實例,實例旨在暴露派生的Promise 實例,Promise就是一種對執行結果不確定的一種預先定義,如果成功,就xx;如果失敗,就xx,就像事先給出了一些承諾。

  用法:

一個最完整的寫法:

var defer1 = $q.defer();

       function fun() {
           var deferred = $q.defer();
           $timeout(function () {
               deferred.notify("notify");
               if (iWantResolve) {
                   deferred.resolve("resolved");
               } else {
                   deferred.reject("reject");
               }
           }, 500);
           return deferred.promise;
       }

       $q.when(fun())
               .then(function(success){
                   console.log("success");
                   console.log(success);
               },function(err){
                   console.log("error");
                   console.log(err);
               },function(notify){
                   console.log("notify");
                   console.log(notify);
               })
               .catch(function(reson){
                   console.log("catch");
                   console.log(reson);
               })
               .finally(function(final){
                   console.log('finally');
                   console.log(final);
               });
1、通過$q服務註冊一個延遲對象
var deferred=$q.defer();

  2、成功解決(resolve)了其派生的promise。參數value將來會被用作successCallback(success){}函數的參數value。

 deferred.resolve(success)

 3、未成功解決其派生的promise。參數reason被用來說明未成功的原因。此時deferred實例的promise對象將會捕獲一個任務未成功執行的錯誤,promise.catch(errorCallback(reason){...})。

 deferred.reject(reason) 

 4、更新promise的執行狀態通知

deferred.notify("notify");

5、對promise進行處理

 $q.when(fun())
               .then(function(success){
                   console.log("success");
                   console.log(success);
               },function(err){
                   console.log("error");
                   console.log(err);
               },function(notify){
                   console.log("notify");
                   console.log(notify);
               })
               .catch(function(reson){
                   console.log("catch");
                   console.log(reson);
               })
               .finally(function(final){
                   console.log('finally');
                   console.log(final);
               });

這裡一般簡寫為:

fun().then(successCallback, errorCallback, notifyCallback);

註:

  deferred的方法中的參數都返回給了promise與callback的參數都是一一對應的,如:

  deferred.resolve(success)的success對應successCallback(success)的success。

這裡在探討下暫時很少用的$q.all().

  $q.all()在多個promise必須執行成功後才能執行成功回調,傳遞值為數組或哈希值,數組中每個值為與Index對應的promise對象。

  這個方法可以將每個promise里的某些重覆代碼或者判斷,只需要在$q.all()的回調處理一次即可,簡化了代碼與工作量。

  寫法為:

var iWantResolve = true;//沒有實際意思,測試運行resolve或reject

       function promise1() {
           return $q(function (resolve, reject) {
               $timeout(function () {
                   if (iWantResolve) {
                       resolve("promise1 resolved");
                   } else {
                       reject("promise1 reject");
                   }
               }, 1000)
           })
       }
       promise1()
               .then(function (s1) {//success callback
                   console.log(s1);
               })
               .catch(function (err1) {//error callback
                   console.log(err1);
               });

       function promise2() {
           var deferred = $q.defer();
           $timeout(function () {
               deferred.notify("promise2 notify");
               if (iWantResolve) {
                   deferred.resolve("promise2 resolved");
               } else {
                   deferred.reject("promise2 reject");
               }
           }, 500);
           return deferred.promise;
       }

       promise2()
               .then(function (s2) {
                   console.log(s2);
               }, function (err2) {
                   console.log(err2);
               });

       $q.all([promise1(), promise2()])
               .then(function (dataArr) {
                   //promise都成功執行後的回調函數
                   console.log("$q.all: ", dataArr);
               }, function (err) {
                   console.log("$q.all: ", err)
               });

  像這個例子,每個promise回調都列印了返回值,那麼可以用$q.all()處理在其回調列印dataArr,則包含了所有promise返回值!

最後附上所有代碼:

View Code

  結語:

   jquery和angular的deferred用法大致相同,但有兩處要註意的地方:

  jquery:

defer=$.Deferred();
defer.promise();

  angular:

var deferred=$q.defer();
deferred.promise;

  以上便是我對angular的$q、deferred、promise的一些淺顯的理解,望各位大神多多評論、指教……

最後附上:

jquery中文網的deferred介紹:

http://www.jquery123.com/category/deferred-object/

一位大神對jquery的deferred的總結!

阮一峰:http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

 


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

-Advertisement-
Play Games
更多相關文章
  • 一、前言 筆者一直覺得,學習一個知識點,你首先要明白,這東西是什麼?有什麼用?這樣你才能瞭解。好了,不說廢話。 1.1、類型轉換為何存在?什麼是類型轉換? 在MVC框架中,都是屬於表示層解決方案,都需要負責收集用戶請求的參數,並且將請求參數傳給應用的控制器組件,但是,這裡有一個問題,客戶端提交的請求 ...
  • 用Sublime Text蠻久了,配置配來配去的,每次換電腦都得重頭再配過,奈何人老了腦子不中用了,得好好整理一些,下次換電腦就有得參考了.. 同事說,他的WebStorm簡直太方便,自身集成了很多方便的工具,不用配置太多 哈哈哈哈但我還是更喜歡用ST 如果要將Sass編譯成css文件,安裝相應的編 ...
  • 當前的應用設計風格趨於Flat扁平化,很多基於BootStrap實現了很多UI非常漂亮的管理界面(Bootstrap admin template)。 此核心文件開源在Github:https://github.com/JackWangCUMT/AdminLTE-Menu-Generate。首先看一 ...
  • 各位好,今天要來介紹如何簡單的修改網站上AngularJS相關Application的內容 進而做到某些效果。(警告!所有的Web Application都應該在後端加上相關驗證) 透過本篇你可以簡單的瞭解到以下 1.如何查找相關的ng物件 2.如何利用ng.element與ng.injector來 ...
  • <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> img { margin: 100px 0px 0px 500px; } #div2 { margin-left: ...
  • 自定義右鍵菜單 技術一般水平有限,有什麼錯的地方,望大家指正。 自定義右鍵菜單,對於一些ERP系統,功能操作比較多,所以我們通常把常用的幾個功能放在自定義的右鍵菜單里方便用戶使用。 實現自定義菜單很簡單,首先我們要屏蔽原始的右鍵菜單,自定義菜單出現在滑鼠的位置,點擊隱藏自定義菜單,過程就是這樣的。 ...
  • Javascript嵌入式 <script typt:javascript>代碼</script> 註釋 //或者/*內容*/ 變數名賦值 Var 變數名 = 值 輸出方式 Document.write(變數名) window.alert(變數名) 算數運算符 a++;a-- 賦值運算符 字元串運算 ...
  • 1、什麼是表單對象 表單(<form>)是Web頁面中的基本元素。表單對象最主要的功能就是能夠直接訪問頁面中的表單。利用表單對象,可以實現與用戶的交互;不需要伺服器的介入,就可以實現動態改變Web頁面的行為。對於Web頁面表單,通常使用document對象的forms數組可以很方便地訪問不同的表單。 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...