雜談-如何與惡勢力做斗爭-異常監(jiān)控和測試

上節(jié), 前后端交互功能基本實現(xiàn), 但在實際工程項目中這其實還不夠操禀。

前端捕捉(懟)后端錯誤

就拿項目中目前還存留的bug舉例:

在后端代碼未啟動的情況下二拐,先運行前端服務,會返還如下錯誤

這是因為后端未返回數(shù)據(jù),導致的語法錯誤
因此, 會產生三個問題

1.程序無法運行
2.頁面不美觀
3.不利排查原因

所以這里需要在不影響程序運行的前提下, 將錯誤以彈窗的形式展示出來,

例如:


此處輸入圖片的描述
此處輸入圖片的描述

這樣不管是對開發(fā)人員,還是用戶都更加友好

具體做法:
在ajax里做一層 狀態(tài)碼的判斷

const ajax = function(request) {

    var r = new XMLHttpRequest()
    r.open(request.method, request.url, true)
    if (request.contentType !== undefined) {
        r.setRequestHeader('Content-Type', request.contentType)
    }
    r.onreadystatechange = function(event) {
        if(r.readyState === 4) {
+            if(r.status == 200) {
+              const data = JSON.parse(r.response)
+              request.success(data)
+            }
+            if(r.status == 500) {
+              request.error()
+            }
        }
    }
    if (request.method === 'GET') {
        r.send()
    } else {
        r.send(request.data)
    }
}   


//用Promise封裝原生ajx
const ajaxPromise = function(url, method, form) {
    var p = new Promise((resolve, reject) => {
        const request = {
            url: url,
            method: method,
            contentType: 'application/json',
            success: function(r) {
                resolve(r)
            },
            error: function(e) {
                const r = {
                    success: false,
                    message: '網絡錯誤, 請重新嘗試',
                }
+               resolve(r)
            },
        }
        if (method === 'post') {
            const data = JSON.stringify(form)
            request.data = data
        }
        ajax(request)
    })
    return p
}

然后在前端把message用彈窗顯示出來

  //請求列表數(shù)據(jù)
  getDataSourseList = async () => {

    const { success, message, data } = await AllService.getList()
+    if(success) {
      this.setState({
        dataSource:data,
      })
+    }else {
+      Message.error(`${message}`)
+    }
  }

Message為antd的彈窗組件, 如果只是簡單顯示可以用alret()

這里分享一個插曲: antd組件的彈窗組件默認的組件名為小寫 message
而我這里協(xié)議定的字段message同樣是小寫, 所以變量沖突,
這個時候我有兩個選擇

  • 要么我認慫,改協(xié)議
  • 要么,和惡勢力懟到底
    我選擇第二個,改了antd源碼, 將小寫換成了大寫 :) 符合我們這次的主題

當然情況還有很多, 到時根據(jù)狀態(tài)碼設置返回信息即可

后端捕捉(懟)前端錯誤

前端在調試過程中,有可能發(fā)送非法數(shù)據(jù)給后端,

后端在不知情的情況下,操作數(shù)據(jù)庫,很有可能會發(fā)生各種靈異事件

所以后端需要對前端傳遞的參數(shù)進行校正, 并發(fā)出提醒

這樣才能更好的和前端合作(撕逼)

具體做法:

  1. 引入校正函數(shù)
//tools/commFunc.js


/**
     * 校驗 前端請求體
     * @param args 前端請求體
     * @param field_list 后端modal定義結構體的 keys
     * @param require_list 必須字段
     * @param is_not_strict 是否嚴格匹配
   */
exports.assemble_args = function (args, field_list, require_list, is_not_strict) {
  let kwargs = {};
  let key_list = [];
  let err_msg = false;

  for (let field_name of field_list) {
    let has_key = (args[field_name] !== undefined);
    if (!is_not_strict) {
      has_key = has_key && (args[field_name] !== '');
    }
    if (has_key) {
      let key = field_name;
      let value = args[field_name];
      if (typeof value === 'string') {
        value = value.trim();
      } else if (field_name == 'id') {
        value = parseInt(value);
      }
      key_list.push(field_name);
      kwargs[key] = value;
    }
  }

  if (require_list && require_list.length) {
    let lack_params = [];
    for (let k of require_list) {
      if (key_list.indexOf(k) == -1) {
        lack_params.push(k);
      }
    }

    if (lack_params.length) {
      err_msg = `lack params:${lack_params.toString()}`
      //throw err_msg;
    }
  }

  return { kwargs, err_msg };
};

exports.goto_err = function (ret, err_msg) {
  ret.success = false;
  ret.message = err_msg;
  ret.code = 400;
  return ret;
};

2.檢查請求體中是否有必須字段, 若缺失, 則把缺失信息發(fā)送給前端

//routes/all/js

main.post('/update', async (request, response) => {

  let ret = {
  "success": true,
  "code": 200,
  "message": "",
  "data": [],
  }

  const body = request.body,
          id = body.id || 0,
          status = body.status || 0
- const args = body
  if (!id) {
    //新建

+    //后端定義的keys
+    const field_list = Object.keys(Model.schema.paths).filter(e=> e!='_id' && e!='id')
+    //檢查請求體中是否有 name, age, address
+    //若缺失,則把缺失信息發(fā)送給前端
+    const { kwargs, err_msg } = commFunc.assemble_args(body, field_list, ['name', 'age', 'address'])

+    if( err_msg ) {
+      let err = commFunc.goto_err(ret, err_msg)
+      response.send(err)
+      return
+    }

    const dataSourceObj = await Model.create(kwargs)

    ret.data = {
      id: dataSourceObj.id, create:true
    }

  } else if (!status) {
    //修改
 +   const kwargs = body

    const dataSourceObj = await Model.findOne({id: kwargs.id})

+    if(!dataSourceObj) {
+      let err = commFunc.goto_err(ret, `dataSourceInfo id:${kwargs.id} query empty`)
+      response.send(err)
+      return
+    }

    for ( let key in kwargs) {
      if(key =='_id' || key =='id' ) {
        continue
      }
      dataSourceObj[key]= kwargs[key]
    }

    const new_dataSourceObj = await dataSourceObj.save()

    ret.data = {
      id: new_dataSourceObj.id, update:true
    }

  } else if (status === -1){
    //刪除
+    const kwargs = body

    const dataSourceObj = await Model.findOne({id: kwargs.id})

+    if(!dataSourceObj) {
+      let err = commFunc.goto_err(ret, `dataSourceInfo id:${kwargs.id} query empty`)
+      response.send(err)
+      return
+    }

    const remove = await dataSourceObj.remove()

    ret.data = {
      id: dataSourceObj.id, delete:true
    }

  }

  response.send(ret)
})

測試失敗示例:

  • 創(chuàng)建時缺少參數(shù)


    此處輸入圖片的描述
    此處輸入圖片的描述
  • 修改, 刪除時,id不存在


    此處輸入圖片的描述
    此處輸入圖片的描述

(完...)

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末缀拭,一起剝皮案震驚了整個濱河市犬耻,隨后出現(xiàn)的幾起案子杠人,更是在濱河造成了極大的恐慌勋乾,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗡善,死亡現(xiàn)場離奇詭異辑莫,居然都是意外死亡,警方通過查閱死者的電腦和手機滤奈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門摆昧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蜒程,你說我怎么就攤上這事绅你。” “怎么了昭躺?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵忌锯,是天一觀的道長。 經常有香客問我领炫,道長偶垮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任帝洪,我火速辦了婚禮似舵,結果婚禮上,老公的妹妹穿的比我還像新娘葱峡。我一直安慰自己砚哗,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布砰奕。 她就那樣靜靜地躺著蛛芥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪军援。 梳的紋絲不亂的頭發(fā)上仅淑,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音胸哥,去河邊找鬼涯竟。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的昆禽。 我是一名探鬼主播蝗蛙,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蝇庭,長吁一口氣:“原來是場噩夢啊……” “哼醉鳖!你這毒婦竟也來了?” 一聲冷哼從身側響起哮内,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤盗棵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后北发,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纹因,經...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年琳拨,在試婚紗的時候發(fā)現(xiàn)自己被綠了瞭恰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡狱庇,死狀恐怖惊畏,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情密任,我是刑警寧澤颜启,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站浪讳,受9級特大地震影響缰盏,放射性物質發(fā)生泄漏。R本人自食惡果不足惜淹遵,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一口猜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧透揣,春花似錦济炎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拆祈,卻和暖如春恨闪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背放坏。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工咙咽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人淤年。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓钧敞,卻偏偏與公主長得像蜡豹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子溉苛,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評論 25 707
  • 也許镜廉, 我不該說愛你, 你和我愚战, 形同陌路娇唯。 也許, 我應該說愛你寂玲, 你和我塔插, 互相牽掛。 也許拓哟, 我應該去恨你想许,...
    諸葛鹵煮閱讀 293評論 0 2
  • 讀經教育,有些人還是不很了解断序,或許是因為我們還有些意思沒有完全表示——雖然我推廣讀經這么久流纹,講了這么多場演講,但大...
    弘謙學堂閱讀 491評論 0 0
  • 34) 不要把投訴逢倍、建議捧颅、爭論的權力和決策的權力混淆。討論并不意味著由全體投票說了算较雕。我們公司文化的特點是極其開放...
    財才閱讀 235評論 0 0