import each from 'lodash-es/each.js'
import cloneDeep from 'lodash-es/cloneDeep.js'
import genPm from 'wsemi/src/genPm.mjs'
import cint from 'wsemi/src/cint.mjs'
import cbol from 'wsemi/src/cbol.mjs'
import delay from 'wsemi/src/delay.mjs'
import Evem from 'wsemi/src/evem.mjs'
/**
* 瀏覽器端之資料同步器
*
* @class
* @param {Object} [opt={}] 輸入設定物件,預設{}
* @param {Boolean} [opt.usePollingTableTags=false] 輸入是否用前端輪詢取得各資料表時間戳布林值,預設false
* @param {Integer} [opt.pollingIntervalTime=2000] 輸入每次輪詢間隔之最小毫秒整數,預設2000
* @returns {Object} 回傳前端資料同步物件,可監聽事件refreshTags、refreshState、refreshTable、getData、error,可使用函數updateTableTags、pollingTableTags
* @example
*/
function WSyncWebdataClient(opt = {}) {
let nowTableTags = {}
let isPolling = false
//default
if (!opt.usePollingTableTags) {
opt.usePollingTableTags = false
}
else {
opt.usePollingTableTags = cbol(opt.usePollingTableTags)
}
if (!opt.pollingIntervalTime) {
opt.pollingIntervalTime = 2000
}
else {
opt.pollingIntervalTime = cint(opt.pollingIntervalTime)
}
//ee
let ee = new Evem()
//eeEmit
function eeEmit(name, ...args) {
setTimeout(() => {
ee.emit(name, ...args)
}, 1)
}
/**
* 直接設定各資料表時間資料
*
* @memberof WSyncWebdataClient
* @param {Object} tableTags 輸入各資料表時間戳物件
* @example
* let tableTags = {...}
* wsdc.setTableTags(tableTags)
*/
function setTableTags(tableTags = {}) {
nowTableTags = tableTags
}
/**
* 主動更新指定資料表之時間戳,當有新的資料表時間戳資料時調用此函數進行更新
*
* @memberof WSyncWebdataClient
* @param {Object} tableTags 輸入各資料表時間戳物件
* @example
* let tableTags = {...}
* wsdc.updateTableTags(tableTags)
*/
async function updateTableTags(tableTags = {}) {
let pms = []
//emit
eeEmit('beforeUpdateTableTags', {
oldTableTags: cloneDeep(nowTableTags),
newTableTags: cloneDeep(tableTags),
})
//needToRefresh
let needToRefresh = false
each(tableTags, (v, k) => {
//原有更新時間戳
let vv = nowTableTags[k]
//check
if (vv !== v) {
needToRefresh = true
}
})
//emit,
eeEmit('refreshState', {
needToRefresh,
oldTableTags: cloneDeep(nowTableTags),
newTableTags: cloneDeep(tableTags),
})
//確認各tags的時間戳
each(tableTags, (v, k) => {
//原有更新時間戳
let vv = nowTableTags[k]
//check
if (vv !== v) {
//pm
let pm = genPm()
//tt
let tt = { tableName: k, timeTag: v, pm }
//push
pms.push(pm)
//emit事件, 外部事件on收到通知時打API去撈指定表數據, 外部由tt.pm回傳成功取得數據或失敗
eeEmit('refreshTable', tt)
//wait
pm
.then((data) => {
//save
nowTableTags[k] = v
//emit, 外部事件on可收到API回傳之數據
eeEmit('getData', { tableName: k, timeTag: v, data })
})
.catch((err) => {
//emit
eeEmit('error', {
msg: 'can not get table data: ' + k,
err,
})
})
}
})
//Promise.all
await Promise.all(pms) //不會有catch
//emit
eeEmit('afterUpdateTableTags', {
oldTableTags: cloneDeep(nowTableTags),
newTableTags: cloneDeep(tableTags),
})
}
/**
* 主動觸發輪詢更新各資料表之時間戳
*
* @memberof WSyncWebdataClient
* @example
* wsdc.pollingTableTags()
*/
async function pollingTableTags() {
//check
if (isPolling) {
return
}
isPolling = true
//emit
eeEmit('beforePollingTableTags')
//pm
let pm = genPm()
//emit, 外部事件on收到通知時打API去撈各資料表時間戳, 需通過pm回傳成功取得數據或失敗
eeEmit('refreshTags', { pm })
//wait
let tableTags = await pm
.catch((err) => {
//emit
eeEmit('error', {
msg: 'can not get tags data',
err,
})
})
//check
if (tableTags) {
//updateTableTags
await updateTableTags(tableTags) //不會有catch
}
//延遲opt.pollingIntervalTime毫秒
await delay(opt.pollingIntervalTime)
//emit
eeEmit('afterPollingTableTags')
//恢復isPolling
isPolling = false
}
//pollingTableTags
if (opt.usePollingTableTags) {
//mouseover
if (typeof window !== 'undefined') {
window.addEventListener('mouseover', (e) => {
pollingTableTags()
}, false)
}
}
ee.setTableTags = setTableTags
ee.updateTableTags = updateTableTags
ee.pollingTableTags = pollingTableTags
return ee
}
export default WSyncWebdataClient