鑒于以下代碼...
function logger = ??
function doSomething() {
logger("doSomething")
console.log("Middle of doing something")
}
是否可以定義logger以產生以下輸出?
"started function doSomething"
"Middle of doing something"
"finished function doSomething"
我考慮了以下幾點:
封裝
doSomething在另一個列印第一行的函式中,doSomething在傳遞引數時呼叫,然后列印最后一行。做之前提到的同樣的事情,但使用裝飾器,所以它更漂亮。
在結束時發送一個事件
doSomething以通知記錄器它完成并使用異步代碼來做到這一點(這有點像在黑暗中拍攝,不確定)
在一次采訪中向我暗示,這可以通過“與堆和呼叫堆疊有關的事情”來實作。
是否有不涉及doSomething告知logger何時完成的解決方案?
uj5u.com熱心網友回復:
我考慮過......用裝飾器封裝......
這就是要走的路。
在結束時發送一個事件
doSomething以通知記錄器它完成并使用異步代碼......
僅當您已經在doSomething.
是否有不涉及
doSomething告訴記錄器何時完成的解決方案?
這就是裝飾器的基本思想。
例子:
let logger = console.log;
// Decorator
function logged(task) {
return function(...args) {
logger("starting " task.name);
const result = task(...args);
logger("ending " task.name);
return result;
};
}
// Your function -- unaware of logger
function doSomething(arg) {
console.log("Middle of doing something with argument " arg);
return arg.toUpperCase();
}
// Decorating...
doSomething = logged(doSomething);
// Run...
let result = doSomething("test");
console.log(result);
uj5u.com熱心網友回復:
使用裝飾器功能
您可以創建一個裝飾器函式來處理同步和異步函式。
因此,如果被修飾的函式回傳 a Promise,我們使用Promise.prototype.finally處理它。
const logger =
(func) =>
(...args) => {
console.log(`Started: ${func.name}`);
const ret = func(...args);
if (ret instanceof Promise) {
return ret.finally(() => console.log(`Ended: ${func.name}`));
} else {
console.log(`Ended: ${func.name}`);
return ret;
}
};
const sleep = (timer) => new Promise((res) => setTimeout(res, timer));
const add = logger(async function add(a, b) {
await sleep(1000).then();
console.log(`Adding ${a} and ${b}`);
return a b;
});
const sub = logger(function sub(a, b) {
console.log(`Subtracting ${b} from ${a}`);
return a - b;
});
console.log(`Result of sub(2, 1): ${sub(2, 1)}`);
add(1, 2).then((res) => console.log(`Result of add(1, 2): ${res}`));
注意:使用該finally方法可確保列印“已結束”日志,即使被修飾的功能失敗。檢查以下示例:
顯示代碼片段
const logger =
(func) =>
(...args) => {
console.log(`Started: ${func.name}`);
const ret = func(...args);
if (ret instanceof Promise) {
return ret.finally(() => console.log(`Ended: ${func.name}`));
} else {
console.log(`Ended: ${func.name}`);
return ret;
}
};
const failingFunction = logger(async function failingFunction(a, b) {
console.log(`Inside: failingFunction`);
throw new Error("Boom");
});
failingFunction().catch(console.error);
uj5u.com熱心網友回復:
我將用異步代碼處理來補充@trincot 的解決方案。
它可以等到異步任務完成并且包裝的函式對裝飾器一無所知
const logStarting = (taskName) => console.log("starting " taskName);
const logFinishing = (taskName) => console.log('ending ' taskName);
const logFailed = (taskName, e) => console.error('The task: ' taskName ' has failed with an error: ', e);
function logged(task) {
const taskName = task.name;
if (task.constructor.name === 'AsyncFunction') {
return async function(...args) {
logStarting(taskName);
try {
const result = await task(...args);
logFinishing(taskName);
return result;
} catch(e) {
logFailed(taskName, e);
thrhow e;
}
}
}
return function(...args) {
logStarting(taskName);
try {
const result = task(...args);
logFinishing(taskName);
return result;
} catch(e) {
logFailed(taskName, e);
thrhow e;
}
};
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/477954.html
標籤:javascript
