[英]Typescript Universal method decorator returning Promise as value
我正在嘗試實現一個可以與原型和實例方法一起使用的通用方法裝飾器。
從下面的代碼中可以看出, instanceMethod() 正在返回一個 Promise。
有沒有辦法可以返回正確的值?
裝飾器代碼:
export function trace(verbose: boolean = false) {
return (target: any, prop: string, descriptor?: TypedPropertyDescriptor<any>): any => {
let fn
let patchedFn
if (descriptor) {
fn = descriptor.value
}
return {
configurable: true,
enumerable: false,
get() {
if (!patchedFn) {
patchedFn = async (...args) => {
const ret = fn.call(this, ...args)
console.log(`typeof ret: ${typeof ret}`)
console.log(`return value: ${ret}`)
return ret
}
}
console.log(`get() patchedFn: ${patchedFn}`)
return patchedFn
},
set(newFn) {
console.log(`set() newFn: ${newFn}`)
patchedFn = undefined
fn = newFn
},
}
}
}
測試類和測試代碼:
class Greeter {
@trace()
public instanceMethod(s: string): string {
return s
}
@trace()
public async instanceAsyncMethod(s: string): Promise<string> {
return s
}
@trace()
public instanceArrowMethod = (s: string): string => {
return s
}
}
async function test() {
const greeter = new Greeter()
const result1 = greeter.instanceMethod('1')
console.log(`* instanceMethod: ${result1}`) // should return '1', instead returns a Promise
const result2 = await greeter.instanceAsyncMethod('2')
console.log(`* instanceAsyncMethod: ${result2}`)
const result3 = await greeter.instanceArrowMethod('3')
console.log(`* instanceArrowMethod: ${result3}`)
}
test()
輸出:
set() newFn: (s) => {
return s;
}
get() patchedFn: (...args) => __awaiter(this, void 0, void 0, function* () {
console.log(`typeof fn: ${typeof fn}`);
const ret = fn.call(this, ...args);
console.log(`typeof ret: ${typeof ret}`);
console.log(`return value: ${ret}`);
return ret;
})
typeof ret: string
return value: 1
* instanceMethod: [object Promise] <<<<<<<<<< The instance method is returning a Promise
get() patchedFn: (...args) => __awaiter(this, void 0, void 0, function* () {
console.log(`typeof fn: ${typeof fn}`);
const ret = fn.call(this, ...args);
console.log(`typeof ret: ${typeof ret}`);
console.log(`return value: ${ret}`);
return ret;
})
typeof ret: object
return value: [object Promise]
* instanceAsyncMethod: 2
get() patchedFn: (...args) => __awaiter(this, void 0, void 0, function* () {
console.log(`typeof fn: ${typeof fn}`);
const ret = fn.call(this, ...args);
console.log(`typeof ret: ${typeof ret}`);
console.log(`return value: ${ret}`);
return ret;
})
typeof ret: string
return value: 3
* instanceArrowMethod: 3
async
函數將始終返回一個承諾。
您已將patchedFn
定義為async
函數,您必須進行修改以將其聲明為普通函數,或者如果有意在調用者處await
。
根據上面愛德華的回答,我用以下代碼解決了這個問題。
我已經在箭頭函數、實例和靜態方法上對其進行了測試。
export function trace(verbose: boolean = false) {
return (target: any, prop: string, descriptor?: TypedPropertyDescriptor<any>): any => {
let fn
let patchedFn
if (target instanceof Function) {
// for static methods return function itself
return target
}
if (descriptor) {
fn = descriptor.value
}
return {
configurable: true,
enumerable: false,
get() {
if (!patchedFn) {
patchedFn = (...args) => {
const ret = fn.apply(this, args)
if (ret instanceof Promise) {
// execute the promise
ret.then((data) => {
return data
}).catch((error) => {
console.log(error)
})
}
return ret
}
}
return patchedFn
},
set(newFn) {
patchedFn = undefined
fn = newFn
},
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.