Git Product home page Git Product logo

Comments (8)

hallettj avatar hallettj commented on August 24, 2024

It looks like you want to wait for the first event (either a value, an error, or the end of the observable), and then make an assertion. I would do that like this:

// create an observable that ends after the first value or error
const firstEvent = db.myData().take(1).takeErrors(1)

// convert the observable to a promise that resolves when the observable ends
await firstEvent.toPromise()

// make assertion here

from kefir.

mAAdhaTTah avatar mAAdhaTTah commented on August 24, 2024

Setting aside what you could do about Kefir in this case, I'd start off by suggesting that your mock is buggy. If the implementation you're mocking is async, your mock should be async as well. The fact that it isn't means the behavior that you're modeling with the mock has different semantics, and the tests that you write aren't going to match the behavior in the real app, causing subtle bugs your test suite won't catch.

Making observe always async would be a major breaking change in the semantics of Kefir's observables, and one that I'm not sure is broadly beneficial. The behavior of Property would end up very different, because code that is depending on observe's synchronous behavior if there's a current event in the Property would now break.

Broadly though, I'd argue you should seek to write your code such that it doesn't actually matter whether it's sync or async, because the Observable abstracts that away from you such that you mostly don't need to know. Obviously, this isn't feasible in every case, but thinking at a higher level about what you're trying to accomplish often leads to solution where it is, and this is one of those cases.

@hallettj's solution is spot on here, since what you're actually trying to do it is get the first value and assert against it, so take(1) is definitely the way to go. Whether you decide to take(1).observe() or take(1).toPromise() and use the value that way depends on larger contexts, although I tend to prefer to stay in "Observable land" as much as possible so would prefer the former.

I'm going to close this issue, as there's nothing actionable here (we can't change `observe) to be always-async) but I'm happy to help if you have follow-up questions, so feel free to reply to this issue.

from kefir.

dmurvihill avatar dmurvihill commented on August 24, 2024

I didn't implement the mock and don't control it, and to turn your argument around I'd argue you should seek to implement observe such that it doesn't actually matter whether the subscribe callback is sync or async. After all, the goal is to abstract it away such that the caller mostly doesn't need to know and that is not accomplished here.

The answer is not to make observe always asynchronous -- nobody asked for that -- but rather to pass the subscription object into the onValue and onError callbacks as a parameter, as I suggested above. The subscription always exists when the callback is executing (I sincerely hope) so it should be a non-breaking change to pass it as a second parameter.

I'll follow up with a pull request. In the meantime, I will take @hallettj's advice and use take.

from kefir.

dmurvihill avatar dmurvihill commented on August 24, 2024

#298

from kefir.

mAAdhaTTah avatar mAAdhaTTah commented on August 24, 2024

I wouldn't want to encourage people to use the callback to onValue in the subscribe callback to determine whether or not to cancel a subscription. There are a number of operators which you can use to trigger an completion of the observable. In your example, the answer was to use take(1). There are others (takeWhile comes to mind as relevant to the discussion here), but broadly, within the onValue callback isn't where that decision should be made, so to speak.

So I'd be opposed to the proposed change in #298 but I'd be interested in hearing from other maintainers on this.

from kefir.

hallettj avatar hallettj commented on August 24, 2024

I'm also opposed to making the subscription object available in the callback. I think it's an unnecessary API complication.

from kefir.

mAAdhaTTah avatar mAAdhaTTah commented on August 24, 2024

@kefirjs/core Anyone in support of this change? If not, I'm going to close this out.

from kefir.

dmurvihill avatar dmurvihill commented on August 24, 2024

It's been 7 days now and no positive interest so I'm going to go ahead and close this. Cheers and thanks for helping out w/ alternatives.

from kefir.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.