[英]TS/JS : conditional async function?
我有一个交易算法根据从 stream 数据中收到的价格下订单。 在生产中,我们从 WS 套接字接收价格,因此它自然是异步的。
不过,我们想用同步发送到算法的预加载价格来测试我们的算法。 问题是,由于该算法在生产中是完全异步的,所有 function 都被标记为 async 并且其中有 await 调用。 但是,在“测试”模式下,所有异步函数实际上都会立即返回Promise.resolve(whatever)
,因为一切都是假的(价格是假的,下订单是假的等),我们不会等待来自互联网的任何东西。
问题是,由于所有这些函数都是异步的,尽管它们立即返回promise.resolve(whatever)
,但如果它们直接返回whatever
,它们的速度要慢得多。
我的问题是:是否可以在 JS/TS 中使用“awaitOrNot”调用“asyncOrNot”函数? 如果不是,在这种情况下可以想到什么方法来摆脱所有异步开销时间,使“假”环境更快? 我想避免维护两种不同的算法(一种生产异步一种,另一种同步一种用于测试目的)
只需一小段代码即可了解我想要什么:
abstract class PriceStream {
onPriceCallback: (price: number) => PromiseOrNot<void>
abstract startStreaming(): void
}
class RealAsyncPriceStream extends PriceStream {
startStreaming() {
// this is not real WebSocket functions but it's just for you to understand
// that prices are arriving and sent asynchronously to the callback here
webSocket.onMessage((message) => {
const price = ... // do formatting of message to a price
this.onPriceCallback(price)
})
webSocket.start()
}
}
class FakeSyncPriceStream extends PriceStream {
startStreaming() {
const prices = [0.6, 0.8, 0.9, 0.10]
for (price of prices) {
this.onPriceCallback(price)
}
}
}
class Algo {
constructor(priceSteam: PriceStream) {
priceStream.onPriceCallback = this.onPrice.bind(this)
}
run() {
priceStream.startStreaming()
}
asyncOrNot onPrice(): PromiseOrNot<void> {
// perform business operations that are :
// - all asynchronous in production (placing and cancelling order awaits for the broker response)
// - all synchronous in fake environment : placing and cancelling orders only locally in memory : all async function return immediately Promise.resolve(...)
}
}
这是一个有趣的想法。 就像我在评论中所说的那样,可以使用隐藏原生 impl 的自定义 promise impl。 您需要将其作为 polyfill 应用以覆盖globalThis.Promise
。
将 TS 编译目标设置为ES2016
或更小,编译后的 JS 代码将不使用async/await
语言功能。 相反,它使用生成器和 Promise,这将使您的自定义 impl 工作。
下面是我的实现。 它会自动适应同步和异步行为,具体取决于您在实例化 Promise 时是否同步调用resolve/reject
回调。 未准备好生产,因为接口不符合规范。 但足以证明这个想法。
const RealPromise = globalThis.Promise
class SyncPromise {
static resolve(value) {
return new SyncPromise((resolve) => resolve(value))
}
constructor(callback) {
this.status = 'pending'
this.resolve = (value) => {
this.status = 'resolved'
this.value = value
this.run()
}
this.reject = (value) => {
this.status = 'rejected'
this.value = value
this.run()
}
this.callbacks = []
try {
callback(this.resolve, this.reject)
} finally {
if (this.status === 'pending') {
return new RealPromise((resolve, reject) => {
this.callbacks.push([resolve, reject])
})
}
}
}
then(onFulfilled = (x) => x, onRejected = (x) => x) {
return new SyncPromise((rs, rj) => {
switch (this.status) {
case 'pending':
break
case 'resolved':
rs(onFulfilled(this.value))
break
case 'rejected':
rj(onRejected(this.value))
break
}
})
}
run() {
const callbacks = this.callbacks
this.callbacks = []
for (let [onFulfilled, onRejected] of callbacks) {
if (this.status === 'resolved') {
onFulfilled(this.value)
} else if (this.status === 'rejected') {
onRejected(this.value)
}
}
}
}
globalThis.Promise = SyncPromise
async function main() {
let value = await Promise.resolve(42)
console.log(value)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.