爲何要用雲開發作錯誤日誌:html
基於以上的緣由,在小程序雲開發剛出來沒多久,我就開始着手在個人小程序上嘗試構建一個錯誤日誌:數據庫
通常用一門新技術的第一步,你須要先瀏覽一下小程序雲開發的官方文檔:
https://developers.weixin.qq....json
初始化環境
而後你須要一個小程序,一個小程序開發工具:
新建一個空白的小程序後,點擊左上角的雲開發按鈕,初始化一個雲開發的環境
小程序
我這裏給它取名叫error-storage。固然我是由於以後個人小程序也不太可能會用到雲開發作後臺,因此能夠浪費一個環境命名。若是你是要用雲開發作後臺業務的話。那麼仍是按照微信推薦,一個作測試一個作正式,命名也儘可能規範一點。
而後它的環境限制也是咱們目前不拿它當主要後端腳本的主要緣由之一。
ok,點擊肯定就建立了一個雲開發後臺了。後端
而後咱們回到代碼。promise
咱們須要寫後端腳本記錄錯誤信息,那麼根據雲開發的文檔,咱們須要修改project.config.json
給他配置一下小程序代碼放在哪裏,後端代碼放在哪裏。
如下是個人配置:微信
我把小程序文件都放在了根目錄下的client文件夾內,而云函數的文件則都放在了根目錄的server文件夾的cloudFunctions裏
那麼如今咱們的目錄結構是這樣的。咱們須要手動移動一下咱們的小程序代碼。網絡
注意這裏project.config.json是在根目錄微信開發
如今先添加一個數據庫集合,打開雲開發控制檯,點擊數據庫。添加一個叫errors的集合閉包
編寫接收錯誤的雲函數
而後咱們先開始寫接收錯誤的雲函數
// 雲函數入口文件 const cloud = require('wx-server-sdk'); cloud.init(); const db = cloud.database(); const errorCllection = db.collection('errors'); function addError(data) { return errorCllection.add({ data: { ...data, createTime: Date.now() } }); } // 雲函數入口函數 exports.main = async event => { event.openid = event.userInfo.openId; delete event.userInfo; await addError(event); return true; };
這面這段代碼很簡單就是將小程序端傳過來的錯誤寫進數據庫裏面,錯誤信息是什麼由小程序端決定,它僅僅只是將全部數據丟進數據庫去而已
保存字後再次右鍵cloudFunctions選擇上傳並部署。那麼咱們的服務端就基本搞定了。(好簡單啊)
寫小程序端的錯誤處理函數
首先,根據教程,咱們要在app.js裏面作雲能力初始化
在app.js的第一行添加代碼
try { wx.cloud.init({ // 雲開發初始化 env: '雲環境id', traceUser: true }); } catch(err) {}
給它加上catch是由於防止出現一些錯誤致使app.js運行失敗,那簡直是災難吧!
這裏的env是你的雲環境id,那麼在哪裏拿呢,在這裏
而後咱們在client/utils文件夾裏面添加一個處理錯誤的模塊吧
名字就叫 error.js
const { config } = require('./config.js'); global.onError = function (message, showModal = true) { return function (error) { wx.hideLoading(); if (showModal) { wx.showModal({ title: '錯誤', content: error.msg || message, // 這裏的error.msg是由於與後端約定若是有什麼錯誤,則帶一個msg的描述 // 而message則是傳入進來備用的錯誤信息 confirmText: '返回首頁', cancelText: '繼續操做', success: res => { if (res.confirm) { // 從新加載首頁 wx.switchTab({ url: '/pages/index/index' }); } else { // 取消就無論了 } } }); } // 上傳到小程序雲數據庫 try { let userInfo = getApp().globalData.userInfo, systemInfo = wx.getSystemInfoSync(), page = getCurrentPages(); // 只有不在開發工具上觸發的才上報 if (systemInfo.platform !== 'devtools') { wx.getNetworkType({ success: res => { wx.cloud.callFunction({ name: 'errorHandler', data: { username: userInfo.nickName, uid: userInfo.id, clientType: systemInfo.model, systemInfo: JSON.stringify(systemInfo), pageRoute: page[page.length - 1].route, message: error.msg || message, version: config.version, networkType: res.networkType, errorTime: new Date(), error: typeof error === 'object' ? JSON.stringify(error) : String(error) } }); } }); } } catch(err) {} console.error('程序發生錯誤:\n', '時間:\n', new Date(), '\n錯誤信息:\n', message, '\nvvvvvvvvvvvvvv\n', error); }; };
如上,除了錯誤信息以外,還儲存了系統信息,網絡類型,最頂部的頁面路由,錯誤時間,用戶信息,版本號等(這裏我加了個config.js用以儲存版本號,版本描述等信息)
用try catch包起來也是爲了防止觸發錯誤致使死循環
而且爲了方便使用,我將其直接掛載到global。不喜歡全局變量的童鞋能夠選擇export出去再引用
而且在觸發錯誤的時候彈出一個提示框提示錯誤了。
錯誤處理函數的使用
那麼接下來就是對這個方法的使用了,首先咱們要監聽app.js的onError方法,小程序頁面邏輯出現錯誤都會到這個方法內
request('./utils/error.js'); // 別忘了引入error.js App({ onError: global.onError('程序發生錯誤') // 這裏返回接受錯誤的函數的閉包,而且傳入的'程序發生錯誤'則是未知錯誤發生時的提示語 });
而其餘的應用基本是應用到在promise的錯誤監聽上,因爲promise中的錯誤不會被app.js的onError接收到,因此咱們須要在每一個promise的catch中使用global.onError
這也是我爲何將onError掛載global的緣由,由於基本每一個頁面都會用到,因此每一個頁面去引用的話很麻煩
例子:
demo.js
Page({ onLoad() { wx.showLoading(); this.requestList() .then(res => { // 作一些事情 }) .catch(global.onError('獲取列表數據失敗!')); }, requestList() { return new Promise((resolve, reject) => { wx.request({ url: 'https://mock.com/aaa', success: resolve, fail: reject }); }); } });
那麼,到如今,基本上已經完成了,愉快的開發,不再擔憂出現徹底沒有頭緒的錯誤啦
最後貼一張我收集到的錯誤吧。可是有些字段我作了調整
最後仍是要吐槽一下微信自己它本身的bug有點多。實在是很無奈的