今天本身寫小程序的時候,近乎被異步搞到崩潰,不停地嵌套回調(我知道 await 和 promise,可是我嫌promise寫起來跟裹腳布似的,而await我怕有兼容性問題也歷來沒有試過)
言歸正傳,將小程序的異步調用變爲同步(如下教程適用於全部異步,只是給小程序作了一下封裝)。
原理:增長事件隊列,採用事件回調來完成同步化es6
如下代碼複製粘貼到控制檯便可測試效果;
這裏直接寫es6代碼了,先寫個定時器版本的方便測試與理解
先寫個無註釋版本的,方便直接看代碼json
class Async{ constructor() { this.list = []; this.sock = false; } request(obj) { setTimeout(() => { console.log(obj); this.sock = false; if(this.list[0]) this.do(this.list.shift()); }, 1000) } do(requestObj, sync) { if(!sync) { return this.request(requestObj); } if(this.sock) { this.list.push(requestObj); }else { this.sock = true; this.request(requestObj); } } }
-----------如下爲註釋版本-----------小程序
class Async{ constructor() { this.list = []; // 定義 執行隊列 this.sock = false; // 判斷是否有任務正在執行 } request(obj) { setTimeout(() => { console.log(obj); this.sock = false; // 重置爲沒有任務正在執行 if(this.list[0]) // 若是隊列中還有任務,執行下一個任務 this.do(this.list.shift()); }, 1000) // 模擬一個異步,一秒後執行任務,執行完成後執行下一個異步任務 } do(requestObj) { if(this.sock) // 若是有任務在執行 this.list.push(requestObj); // 將當前任務其增長到任務隊列 else { this.sock = true; // 不然開始執行當前任務並設定'有任務在執行' this.request(requestObj); } } } var x = new Async(); x.do({url: 1}); // 一秒後打印 url: 1 x.do({url: 2}); // 兩秒後打印 url: 2
可是同步只是異步迫不得已的選擇,因此不能所有否決掉異步promise
class Async{ constructor() { this.list = []; // 定義 執行隊列 this.sock = false; // 判斷是否有任務正在執行 } request(obj) { setTimeout(() => { console.log(obj); this.sock = false; // 重置爲沒有任務正在執行 if(this.list[0]) // 若是隊列中還有任務,執行下一個任務 this.do(this.list.shift()); }, 1000) // 模擬一個異步,一秒後執行任務,執行完成後執行下一個異步任務 } do(requestObj, sync) { if(!sync) // 判斷是否須要同步,若是須要再加入到隊列,否則直接執行 return this.request(requestObj); if(this.sock) // 若是有任務在執行 this.list.push(requestObj); // 將當前任務其增長到任務隊列 else { this.sock = true; // 不然開始執行當前任務並設定'有任務在執行' this.request(requestObj); } } } var x = new Async(); x.do({url: 1}, true); // 一秒後打印 url: 1 x.do({url: 2}, true); // 兩秒後打印 url: 2 x.do({url: 3}); // 一秒後打印 url: 3
而後加入小程序的接口調用方法app
class AsyncRequest{ constructor() { this.list = []; // 定義 執行隊列 this.sock = false; // 判斷是否有任務正在執行 } request(obj) { wx.request({ url: obj.url, data: obj.data, header: { 'content-type': 'application/json' }, success: res => { obj.cb(res); if(this.list[0]) this.do(this.list.shift()); } }) } do(requestObj, sync) { if(!sync) // 判斷是否須要同步,若是須要再加入到隊列,否則直接執行 return this.request(requestObj); if(this.sock) // 若是有任務在執行 this.list.push(requestObj); // 將當前任務其增長到任務隊列 else { this.sock = true; // 不然開始執行當前任務並設定'有任務在執行' this.request(requestObj); } } } var x = new AsyncRequest(); x.do({url: 1, data: {test: 1}, cb: ()=> {}}, true); // 先請求接口1 x.do({url: 2}, true); // 1 請求完成後請求接口2 x.do({url: 3}); // 和 1 同時 發起請求