import get from 'lodash-es/get.js'
import isfun from './isfun.mjs'
/**
* 取設定物件之觀察回調(opt.onTrace),回傳通知函數或null,供計時器相關函數(輪詢、偵測、重試、節流、防抖、排程、逾時、等待)共用同一套規則,不各自手寫
*
* 本函數供wsemi自身與其他自有套件(w-*)之計時器相關函數取得觀察回調,統一以單一擁有者實作,避免各套件自寫等價版本而分歧。觀察回調用於讓測試與診斷以「事件發生」而非「等待毫秒」同步,規則見sgud/rule/rulebook.md之R-TRACE-01
*
* 觀察回調於函數內部之事件發生當下同步呼叫,傳入一個凍結之事件物件{ type, ... }:type為各函數於JSDoc列舉之固定字串,其餘欄位為原始值(數字、字串、布林或null)之快照,不含內部可變狀態與Error物件
*
* 回調不帶接收者呼叫(this為undefined),回傳值不使用;其同步拋錯與回傳Promise之rejection皆忽略,故不中斷被觀察之函數、不改變其結果,亦不產生未處理之rejection
*
* opt.onTrace未給或非函數時回傳null,呼叫端以if (trace)略過組事件物件,使未傳回調時之行為、時序與效能同未支援前;函數被釋放(停止、清除)後呼叫端不應再通知
*
* Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/getTrace.test.mjs Github}
* @memberOf wsemi
* @param {Object} [opt={}] 輸入設定物件,取其onTrace屬性,預設{}
* @param {Function} [opt.onTrace=null] 輸入觀察回調函數,格式為(e)=>{},e為凍結之事件物件{ type, ... },預設null
* @returns {Function|null} 回傳通知函數,格式為(type, info)=>{},type為事件類型字串,info為事件之其餘欄位物件;opt.onTrace非函數時回傳null
* @example
*
* //被觀察函數之內部
* function work(opt = {}) {
* let trace = getTrace(opt)
* let n = 0
* let t = setInterval(() => {
* n++
* if (trace) {
* trace('tick', { n })
* }
* if (n >= 2) {
* clearInterval(t)
* }
* }, 10)
* }
*
* //使用端
* work({
* onTrace: (e) => {
* console.log(e)
* },
* })
* // => { type: 'tick', n: 1 }
* // => { type: 'tick', n: 2 }
*
*/
function getTrace(opt) {
let fn = get(opt, 'onTrace', null)
if (!isfun(fn)) {
return null
}
return (type, info) => {
try {
let r = fn(Object.freeze({ type, ...info }))
if (r && isfun(r.catch)) {
r.catch(() => {})
}
}
catch (err) {}
}
}
export default getTrace