使用APICloud開發App的效能優化探索——合理使用同步/非同步介面

模擬演算法發表於2022-01-19

本文從同步/非同步原理角度出發,介紹了App的優化方法,靈活使用這些方法,可以在開發App時給使用者帶來更好的使用體驗。

標準的JavaScript的執行分為同步和非同步兩種模式,APICloud的所有擴充套件API也同樣支援同步或非同步的呼叫,它們適用於不同的場景。

在瀏覽器引擎中,JavaScript引擎是單執行緒執行的,單執行緒意味著在同一時間內只能有一段程式碼被JavaScript引擎執行。所以JavaScript函式以一個接一個的棧方式執行,A函式如果依賴B函式的返回結果,那麼A函式必須同步等待B函式返回的結果後才有執行機會。

JavaScript的同步模式符合開發人員通常的編碼習慣,但效能問題也因此而起,當函式棧中某個函式的執行耗費時間過長時,將引起函式棧中後邊的所有函式延遲執行,引發程式效能問題。這在移動端體驗場景優先的場景下是無法接受的。
非同步模式因此誕生。APICloud所有的擴充套件API在現有的JavaScript同步模式的基礎上,引入了JavaScript CMD (Common Module Definition) 的模組化定義規範,API的呼叫遵循AMD(Asynchronous Module Definition)的非同步方式載入,通過實現AMD規範下的JavaScript 非同步載入模式,能夠很好地解決效能問題。

APICloud的JavaScript非同步程式設計模式可以總結為三個關鍵詞:回撥函式、事件監聽和require。典型的程式碼使用如下:

<script>
    function readFile(){
    var fs = api.require('fs');
    fs.read({
        fd:'fileId'
    },printFile);
    console.log('readFile執行完畢....');
}
//回撥函式
function printFile(ret,err){
    if(ret.status){
        var text = ret.data;
        console.log('printFile內容:'+ text);
    }else{
        console.log(JSON.stringify(err));
    }
}
</script>

當呼叫fs模組的read函式時,將進入對應原生Android和ios系統層操作,將在原生子執行緒中執行檔案讀取的操作。操作結束後,將回撥JavaScript。這樣做的好處在於,App不會因為讀取檔案大小,耗時不同而引起阻塞,如果此時裝置正在進行UI渲染,將產生“卡頓”的問題,以上程式碼日誌輸出順序為:

console.log('readFile執行完畢....');
//若干時長後,因檔案大小而花費時長不一
console.log('printFile內容:'+ text);

非同步的模式能夠讓App的邏輯功能與UI渲染很好地解耦,將耗時的操作放在多執行緒裡執行,充分利用裝置的硬體效能,使App更專注於渲染,提供更好的視覺效果及響應速度給使用者。

在APP開發過程中,可以根據不同的操作場景,合理地將同步操作與非同步操作相結合,編寫出結構更合理、效能更出色、維護更方便的JavaScript程式碼。

APICloud擴充套件的API中,支援同步操作的api物件介面通過傳入sync引數進行同步操作宣告;支援同步操作的模組介面以Sync結尾。
(1) 使用同步的介面獲取App快取大小,相關API呼叫方法的程式碼如下:

//同步呼叫
function sycacheSize() {
    var size = api.getCacheSize({
        sync: true
    });
    alert('快取大小為:' + size + '位元組');
}
//非同步呼叫
function aycacheSize() {
    api.getCacheSize(function (ret) {
        var size = ret.size;
        alert('快取大小為:' + size + '位元組');
    });
}

(2)使用同步介面判斷偏好設定,程式碼如下

//同步呼叫
function isLoginSyc() {
    var Login = api.getPrefs({
        sync: true,
        key: 'is_login'
    });
    alert('登入狀態:' + login);
}
//非同步呼叫
function isLoginAyc() {
    api.getPrefs({
        key: 'is_login'
    }, isLoginCallback);
}
function isLoginCallback(ret) {
    var login = ret.value;
    alert('登入狀態:' + login);
}

相關文章