It needs classes and a logger just in case
class CatRetrievalError extends Error {
constructor(message) {
super(message);
this.name = 'CatRetrievalError';
}
}
class Logger {
static instance = null;
static getInstance() {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
log(message) {
console.log(`[CatSystem Log: ${new Date().toISOString()}] ${message}`);
}
}
class TimeProvider {
getCurrentTime() {
return new Date();
}
}
class CatEmojiFactory {
static createMorningCat() {
return '🐈⬛';
}
static createAfternoonCat() {
return '🐈';
}
}
function logDecorator(target, propertyKey, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args) {
Logger.getInstance().log(`Entering ${propertyKey} with args: ${JSON.stringify(args)}`);
const result = originalMethod.apply(this, args);
Logger.getInstance().log(`Exiting ${propertyKey} with result: ${JSON.stringify(result)}`);
return result;
};
return descriptor;
}
class CatService {
constructor(timeProvider) {
this.timeProvider = timeProvider || new TimeProvider();
}
@logDecorator
async getCatAsync() {
return new Promise((resolve, reject) => {
try {
setTimeout(() => {
const currentHour = this.timeProvider.getCurrentTime().getHours();
Logger.getInstance().log(`Current hour determined: ${currentHour}`);
if (currentHour < 12) {
resolve(CatEmojiFactory.createMorningCat());
} else {
resolve(CatEmojiFactory.createAfternoonCat());
}
}, 100);
} catch (error) {
reject(new CatRetrievalError(`Failed to retrieve cat: ${error.message}`));
}
});
}
}
class CatObservable {
constructor() {
this.observers = [];
}
subscribe(observer) {
this.observers.push(observer);
}
notify(cat) {
this.observers.forEach(observer => observer(cat));
}
}
const getCat = async () => {
const catService = new CatService();
const catObservable = new CatObservable();
catObservable.subscribe(cat => {
Logger.getInstance().log(`Observer notified with cat: ${cat}`);
});
try {
const cat = await catService.getCatAsync();
catObservable.notify(cat);
return cat;
} catch (error) {
Logger.getInstance().log(`Error: ${error.message}`);
throw error;
}
};