繁体   English   中英

TS/JS:条件异步 function?

[英]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回调。 未准备好生产,因为接口不符合规范。 但足以证明这个想法。

TS游乐场

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM