Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

367
Visualizações
TS/JS : conditional async function?

I have a trading algorithm placing orders depending on prices it receives from a stream of data. When in production, we receive prices from a WS socket, so it is naturally asynchronous.

Though, we wanted to test our algorithm with pre-loaded prices sent to the algorithm synchronisly. The problem is that, as the algorithm is fully asynchronous in production, all function are marked async and have await calls in them. Though, in the "test" mode, all that async functions actually return Promise.resolve(whatever) immediately because everything is fake (prices are fake, placing order is fake etc.) and we don't wait for anything from the Internet.

The problem is that, as all these functions are asynchronous, despite they return immediately a promise.resolve(whatever), they are much slower that if they returned whatever directly.

My question is : is it possible to make "asyncOrNot" functions in JS/TS that would be called with "awaitOrNot" ? If not, what approach can be thought of in this situation to get rid of all the async overhead time, to make the "fake" environment faster ? I'd like to avoid to maintain 2 different algorithms (one production async one and another sync one for test purposes)

Just a little piece of code to understand what I'd like :

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(...)
    }
}
about 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

It's an interesting idea. Like I said in comment, it's possible with a custom promise impl that shadows the native impl. You need to apply it as polyfill to override globalThis.Promise.

With TS compile target set to ES2016 and lesser, compiled JS code will not using async/await language feature. Instead it uses generator and Promise, which will put your custom impl to work.

Below is my impl. It automatically adapts to sync and async behavior, depending on whether you synchronously call the resolve/reject callback when instantiating Promise. Not production ready because interface is not aligned to spec. But enough to demonstrate the idea.

TS Playground

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)
}

about 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda