最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

小程序異步問題之多個網(wǎng)絡請求依次執(zhí)行并依次收集請求結(jié)果

 更新時間:2019年05月05日 09:23:22   作者:JabinGP  
這篇文章主要介紹了小程序異步問題之多個網(wǎng)絡請求依次執(zhí)行并依次收集請求結(jié)果,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

業(yè)務邏輯

最近開發(fā)一個便簽小程序的時候,有這樣一個需求:用戶可以在寫便簽的時候添加一個或多個圖片。

對于這個需求,我們用戶按下保存鍵時,內(nèi)部具體的實現(xiàn)上是這樣的邏輯:

  1. 首先檢測用戶是否傳入了圖片,如果存儲本地圖片地址的數(shù)組長度>=1,則將圖片數(shù)組放入上傳圖片的函數(shù)。
  2. 由于小程序網(wǎng)絡請求大小限制,我們只能采取循環(huán)上傳單文件,然后收集每次請求的結(jié)果--圖片在服務器的地址,最后將結(jié)果放在一個數(shù)組中供后續(xù)的操作使用。
  3. 當圖片上傳函數(shù)全部執(zhí)行完畢后,將數(shù)組中的圖片數(shù)組取出來,賦值到日記對象中,再將整個日記對象提交到服務器。
  4. 服務器返回保存成功或失敗。

思路其實非常清晰簡單,但是在代碼實現(xiàn)上卻翻了大跟頭。

異步帶來的問題

小程序的網(wǎng)絡請求是異步的:我們無法通過return來將網(wǎng)絡請求結(jié)果返回出來使用。

  wx.request({

     //...省略其他屬性

     success: function (res) {

     },

     fail: function (res) {

     }

  })

例如在微信中發(fā)送網(wǎng)絡請求,我們只能使用微信提供的方法wx.xxx,其中請求的結(jié)果保存在res中,而res無法直接return得到。

解決:res雖然無法直接獲取,但是我們能通過將需要使用到這個請求結(jié)果的業(yè)務邏輯代碼放入這個網(wǎng)絡請求的回調(diào)函數(shù)中直接讀取網(wǎng)絡請求結(jié)果,也就是一切都需要通過回調(diào)來解決。

  wx.request({

     //...省略其他屬性

     success: function (res) {

      console.log(res);

      //接業(yè)務邏輯代碼

     },

     fail: function (res) {

      console.log(res);

     }

  })

例如這個微信的網(wǎng)絡請求,我們可以通過success和fail的回調(diào)函數(shù)來讀取res的值從而完成依賴res結(jié)果的業(yè)務邏輯。

回調(diào)地獄

雖然解決了結(jié)果獲取的問題,但是又產(chǎn)生了另一個問題,當多個請求中有明確的先后順序時,回調(diào)會嵌套的很厲害,造成回調(diào)地獄,代碼可讀性和可維護性都會很差。

例如對于一個日記頁面,需要先請求到頁面的數(shù)據(jù)(里面包含了圖片數(shù)據(jù)和其他數(shù)據(jù)的地址),再根據(jù)頁面數(shù)據(jù)去請求圖片數(shù)據(jù)后再請求音頻數(shù)據(jù)。例如以下代碼:

  //請求頁面整體數(shù)據(jù)

  wx.request({

     //...省略其他屬性

     success: function (res) {//成功

        //請求圖片數(shù)據(jù)

        wx.request({

         success: function (res) {//成功

           //請求音頻數(shù)據(jù)

           wx.request({

             success: function (res) {//成功

             },

             fail: function (res) {//失敗

               console.log("請求失敗:"+res);

             }

           })

         },

         fail: function (res) {//失敗

           console.log("請求失敗:"+res);

         }

        })

     },

     fail: function (res) {//失敗

       console.log("請求失敗:"+res);

     }

  })

如何優(yōu)化?幸運的是,在es6里面我們可以用promise去優(yōu)化我們的回調(diào),用then代替回調(diào),首先將網(wǎng)絡請求封裝成一個Promise:

// 后臺post請求

  function postRequest(posturl, postdata) {

   return new Promise((resolve, reject) => {

    wx.request({

     //省略其他屬性

     success: function (res) {

      console.log("at post request: 請求成功")

      resolve(res.data)//設置promise成功標志

     },

     fail: function (res) {

      console.log("at post request: 請求失敗")

      reject(res.data)//設置promise失敗標志

     }

    })

   });

  }

這樣封裝以后,我們的網(wǎng)絡請求會在success和fail后回調(diào)resolve,這樣可以告訴promise,“hey,我完成我的工作了,你可以進行你的then操作了”,這樣就可以用then來簡化嵌套邏輯。使用promise來完成上面那個問題的請求將會是這樣的:

 postRequest(posturl,postdata)

  .then(function(res){

   //業(yè)務邏輯

   //調(diào)用下一個請求

   return postRequest(next_posturl,next_postdata);

  })

  .then(function(res){

   //業(yè)務邏輯

   //調(diào)用下一個請求

   return postRequest(next_next_posturl,next_next_postdata);

  })

  .then(function(res){

   //業(yè)務邏輯

  });

是不是簡潔的多~

一個看似簡單的需求

我們的有一個很簡單的需求是需要對一組數(shù)量不定的圖片做分別上傳(因為微信限制所以無法做多上傳),并且在上傳完成以后需要獲取到所有的返回結(jié)果。

那么用我們前面的回調(diào)函數(shù)+then的話,很自然的想到這樣的寫法

postRequest(posturl,postdata)

.then(function(res){

  //獲取返回res

  //上傳下一個圖片

  return postRequest(next_posturl,next_postdata);

})

.then(function(res){

  //獲取返回res

  //上傳下一個圖片

  return postRequest(next_next_posturl,next_next_postdata);

})

.then(function(res){

  //獲取返回res

});

這樣看起來很簡單明了,但是我的圖片數(shù)量是不定的,怎么動態(tài)的構(gòu)建.then.then.then這樣的鏈式調(diào)用呢?經(jīng)過我的研究后發(fā)現(xiàn)可以通過一個輔助的promise鏈去完成主鏈的鏈式構(gòu)建。

//多文件上傳

function jabingp_upLoad(uploadurl, files) {

 return new Promise((resolve, reject) => {

  //初始化promise鏈

  var mergedAjax = Promise.resolve();

  var response = [];

  // 循環(huán)上傳

  
  // 這里一定要使用let來為沒一次循環(huán)構(gòu)建一個塊級作用域
  // 使用var則需要配合立即執(zhí)行函數(shù)
  for (let i = 0; i < files.length; i++) {

   mergedAjax = mergedAjax.then(() => {

    return jabingp_upLoadSingle(uploadurl, files[i]).then((res) => {

     response.push(res);

    });

   });

  }

  //當前面循環(huán)中所有的then執(zhí)行完畢時會執(zhí)行這個then

  mergedAjax.then(() => {

   resolve(response);      //設置這個函數(shù)的promise對象為完成狀態(tài)并放入數(shù)據(jù)

  });

 });

}

通過這個函數(shù),就完成了多個請求依次執(zhí)行并收集結(jié)果的效果。這個函數(shù)的重點在于利用另外一個已經(jīng)處于完成狀態(tài)的promise,不斷的迭代自身,在每次迭代的then內(nèi)部通過return來完成輔助鏈到業(yè)務鏈的切換。

2019-04-27 更新

使用await/async更加優(yōu)雅地處理異步吧!

在es7標準中,引入了await和async這對兄弟,它們可以讓我們的異步代碼看起來和同步代碼一樣。讓我們來看看await和async都能做什么吧。

await可以等待一個promise運行到完成狀態(tài)并且獲取結(jié)果,或者等待一個async修飾的函數(shù)運行完成并獲取結(jié)果,但是使用await的時候,必須在async函數(shù)體內(nèi)部。比如我有這樣一個網(wǎng)絡請求:

 function postRequest(posturl, postdata) {

   return new Promise((resolve, reject) => {

    wx.request({

     //省略其他屬性

     success: function (res) {

      console.log("at post request: 請求成功")

      resolve(res.data)//設置promise成功標志

     },

     fail: function (res) {

      console.log("at post request: 請求失敗")

      reject(res.data)//設置promise失敗標志

     }

    })

   });

  }

那么如果不使用await,我就需要這樣取得請求結(jié)果

function test(){
 postRequest(xxx,xxx).then(function(res){
   // 這里面可以讀取請求結(jié)果res了
   console.log(res);
 });
}
test();

可以看到,這樣的代碼不太符合常規(guī)邏輯,我們希望函數(shù)作用是返回數(shù)據(jù),這樣更清晰明了,有了await,我們的愿望就可以實現(xiàn)了。

async function test(){
 let res = await postRequest(xxx,xxx);
 // 下面就可以正常寫對res的讀取了
 console.log(res);
}
test();

注意我給函數(shù)加上了async,有了async和await,我們就可以像同步代碼一樣使用異步請求了~

那么上面那個通過復雜的構(gòu)建鏈完成的需求,通過await實現(xiàn)將會變得非常簡單易懂。

async function jabingp_upLoad(uploadurl, files) {
  let response = [];
 
  // 循環(huán)依次等待上傳結(jié)果
  for (let i = 0; i < files.length; i++) {
    let res = await jabingp_upLoadSingle(uploadurl, files[i]);
    // 結(jié)果放入數(shù)組
    response.push(res);
  }
  // 返回結(jié)果
  return response ;
}

代碼一下子變得簡潔易懂了,注意調(diào)用的時候也同樣需要在一個async函數(shù)內(nèi)部執(zhí)行await。

async function test(){
 let response = await jabingp_upLoad(xxx,xxx);
 console.log(response );
}
test();

是不是非常簡單呢,趕緊在你的異步請求中使用async和await吧~

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論

蒙城县| 宿松县| 永兴县| 常山县| 特克斯县| 喀喇沁旗| 郴州市| 锦屏县| 昔阳县| 清新县| 河北省| 旌德县| 同江市| 新乡市| 郧西县| 菏泽市| 蒙阴县| 泰顺县| 宁阳县| 商河县| 桂平市| 封丘县| 海伦市| 武义县| 突泉县| 温宿县| 南昌县| 江山市| 左贡县| 宣威市| 岳池县| 临沂市| 岗巴县| 巴青县| 武宣县| 江阴市| 普定县| 余干县| 安国市| 炎陵县| 北辰区|