在一個(gè)測(cè)試工具開(kāi)發(fā)中吨灭,發(fā)現(xiàn)在批量生成數(shù)據(jù)的過(guò)程中存在數(shù)據(jù)異常問(wèn)題匪凉。
批量生成數(shù)據(jù)的邏輯設(shè)計(jì)是:根據(jù)要生成案件的數(shù)量些侍,通過(guò)循環(huán)體調(diào)用ajax针肥,反復(fù)調(diào)用Controller里的/batchGenerator接口,每次調(diào)用根據(jù)限制條件生成一個(gè)符合條件的單據(jù)躏尉。
由于ajax的異步特性瞧预,出現(xiàn)數(shù)據(jù)異常大概率是在這個(gè)過(guò)程中存在多線程問(wèn)題谱净,需要在ajax過(guò)程中加以控制防止數(shù)據(jù)異常弊决。最初的嘗試:先改一行代碼噪舀,把a(bǔ)jax方法改成同步的魁淳。
改完后相關(guān)代碼如下(老版本代碼只剩下截圖了,湊合著看):
運(yùn)行了一下發(fā)現(xiàn)与倡,數(shù)據(jù)倒是立馬變正常了~然鵝界逛,,纺座,息拜,,净响,少欺,,
整個(gè)頁(yè)面完全卡住了Σ(o?д?o?)馋贤,這和想象中的完全不一樣哇赞别。。掸掸。氯庆。
明明應(yīng)該點(diǎn)擊按鈕后置灰按鈕蹭秋,然后進(jìn)入循環(huán)后扰付,先更新頁(yè)面進(jìn)度條,再發(fā)同步請(qǐng)求仁讨,結(jié)束后判斷數(shù)量是否滿足羽莺,繼續(xù)循環(huán)或結(jié)束的,
結(jié)果別說(shuō)是每次循環(huán)刷新進(jìn)度條了洞豁,連寫(xiě)在100行之前的點(diǎn)擊按鈕后置灰按鈕的代碼都完全沒(méi)生效盐固!(╯°□°)╯︵┻━┻
查了一下ajax同步方法的特點(diǎn)后發(fā)現(xiàn),js本身是單線程的丈挟。
ajax同步方法會(huì)占用線程而阻塞UI渲染的進(jìn)度刁卜,而script函數(shù)的執(zhí)行優(yōu)先級(jí)又高于頁(yè)面UI加載(比如在頁(yè)面scrpit里寫(xiě)一個(gè)alert,加載頁(yè)面時(shí)先跳出alert曙咽,關(guān)閉后才出頁(yè)面)
所以雖然UI渲染代碼寫(xiě)在前面蛔趴,但在ajax同步面前統(tǒng)統(tǒng)被打住(?_?),這頁(yè)面效果實(shí)在是無(wú)法接受啊例朱。孝情。。
谷歌了一下“ajax同步 UI線程阻塞”洒嗤,找到了一絲光明:deferred對(duì)象箫荡。
defferd對(duì)象是一種基于promise的異步流控制對(duì)象,是一種jQuery的回調(diào)函數(shù)解決方案渔隶,學(xué)習(xí)了一下阮一峰的日志
http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html 羔挡,
對(duì)代碼進(jìn)行第二次修改:
這樣可以將ajax方法設(shè)為異步,然后通過(guò)done或者fail方法進(jìn)行類似同步的控制。再次嘗試之后發(fā)現(xiàn)頁(yè)面不卡了(~ ̄▽ ̄)~
但是數(shù)據(jù)TM又出現(xiàn)異常了 щ(?Д?щ)婉弹。睬魂。。镀赌。氯哮。
仔細(xì)思考一番之后幡然醒悟,關(guān)鍵問(wèn)題好像是在于ajax方法是寫(xiě)在一個(gè)循環(huán)體內(nèi)反復(fù)調(diào)用的商佛。
所以在ajax設(shè)回異步之后喉钢,循環(huán)體執(zhí)行不會(huì)再被卡住了,所以絲滑的連續(xù)發(fā)起請(qǐng)求良姆。
而ajax推送及返回結(jié)果的過(guò)程則存在延時(shí)肠虽,于是又引起了數(shù)據(jù)的異常。
所以繞了一圈這么改和原來(lái)用success玛追,error是一個(gè)樣(╯-_-)╯~╩╩
因而要解決這個(gè)問(wèn)題税课,就要確保一次ajax請(qǐng)求完成之后再發(fā)起下一次,而不能簡(jiǎn)單粗暴的仍到循環(huán)體里痊剖。韩玩。。陆馁。
這下就不是改一兩個(gè)代碼就能解決的了(?_?)找颓,得對(duì)這塊邏輯重構(gòu)一下:
于是ajax請(qǐng)求就被放到了一個(gè)遞歸函數(shù)里面,count和batchNum這兩個(gè)變量控制進(jìn)度叮贩,一次請(qǐng)求完成之后如果進(jìn)度沒(méi)有結(jié)束击狮,則count自增并遞歸調(diào)用。
再次運(yùn)行發(fā)現(xiàn)益老,頁(yè)面不卡了彪蓬,數(shù)據(jù)也正常了(??????)??