Hi Benjamin,
Have done quite some reading today;) Al lot of intellectual jibber-jabber. Most of the stuff has a point, and if you talk long enough, nobody understands the subject anymore.
Let me state 1 think clearly. I think 100% observables is the way forward. Perhaps an added wrapper to enable promises for the situations where they might be a better solution. Let me show you an 100% working wrapper, that would produce a promise just as it is now with $http.
export function http2Prom(req:Request|string) {
return new Promise(function (resolve,reject) {
http2Observable(req)
.retry(3)
.subscribe(resolve,reject)
})
}
I’m assuming you are going to store this in a singleton. Oh, it does a bit more then the current $http, on failure, it retries 3 times before rejecting the promise.
I like the idea of tasks, but those aren’t even on the agenda for es7. Observables are readily available now. (when those land in ES7 it might take some time to rework from RX to that tough!)
Bottom line, if the lowest part of the http2 library is based on observables, it is easy enough to poly-fill other interfaces. The other way around is an uphill battle!
Regards
Sander
Interface | |||
---|---|---|---|
Value | Value | Singular | Spatial |
Getter | Getter | Singular | Spatial |
Setter | Setter | Singular | Spatial |
Array | Value | Plural | Spatial |
Iterator | Getter | Plural | Spatial |
Generator | Setter | Plural | Spatial |
Deferred | Value | Singular | Temporal |
Promise | Getter | Singular | Temporal |
Resolver | Setter | Singular | Temporal |
Stream | Value | Plural | Temporal |
Reader | Getter | Plural | Temporal |
Writer | Setter | Plural | Temporal |
promises are a read only view to a future.
If you were to create a new Promise type that was still a spec-compliant Promise, but allowed cancellation from the promise instance, it would have to cancel the entire promise chain. If that chain were forked at any point, you'll cancel the forks too.
There is no way around this. At the point to do code your way around this, you'll have created a single value observable, svc I doubt that will be spec compliant.
In essence, cancellable promises introduce shared, mutable state. That's a nightmare.
If someone can produce a spec compliant, cancellable, retriable promise, that doesn't kill the entire chain of promises when cancelled, and isn't really just a single value observable, I'll reconsider.
--
You received this message because you are subscribed to the Google Groups "angular-data-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular-data-d...@googlegroups.com.
To post to this group, send email to angular-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/angular-data-dev/e59d0a8a-fc25-422c-9a29-e410d7f41dd1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Observables are not JUST read only views to a future, though. They can actually create those futures. In fact, they could even return different values depending on when you subscribe to them. For example:
Observable.create(o => {
o.onNext(Date.now());
});
They're just a bit more flexible and robust as an abstraction than promises. For a wide variety of reasons.
You've raised some really good point, but with respect: Given that this effort has embraced observable with no intention of changing, and it doesn't seem likely we're going to agree on the color of the shed, I think I'm going to bow out of this thread for now.
To view this discussion on the web visit https://groups.google.com/d/msgid/angular-data-dev/e8942eee-0ab1-447b-8a4b-90dbb9cf3db6%40googlegroups.com.
var currentTime = http('http://sample.com/getCurrentTime.php');
// at this point, no request as been made
currentTime.subscribe(x => console.log(x));
// NOW you're making the AJAX request to get the current time.
// later logs 10:30:00AM
setTimeout(() => {
currentTime.subscribe(x => console.log(x));
// AGAIN! you're making the AJAX request to get the current time.
// later logs 10:30:05AM (in a vacuum, anyhow)}, 5000);
var currentTime = http('http://sample.com/getCurrentTime.php');
// at this point, the AJAX request as been made already.
currentTime.then(x => console.log(x));
// later logs 10:30:00AM
setTimeout(() => {
currentTime.then(x => console.log(x));
// later logs 10:30:00AM again, because it's the same value from the same request}, 5000);
--
You received this message because you are subscribed to the Google Groups "angular-data-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular-data-d...@googlegroups.com.
To post to this group, send email to angular-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/angular-data-dev/356dce65-b13a-4f9b-9482-7d5fd2f35d4f%40googlegroups.com.
Benjamin, Ben,
Shouldn't everything be an observable?
The short answer, Yes. At least in the context of the new NG2 communication layer. I’m glad that it is already decided on this.
Besides what Ben already stated, and what I strongly second, observables enable API simplicity. One can simple use composition to get rid of interceptors.
Developers code becomes much simpler, and at the same time much more powerful.
Let me give you a sample that describes behavior. It is not real code, although it will work if you fill in the blanks.
@inject(userObservable,http,req,userIsAllowed)
function getDataFromAuthuserWith3Retrys(req) {
var result = userObservable()
.filter(userIsAllowed) // check permissions before firing off an request.
.http(req) // set up the request, for when I need it
.map( (x) => { log(x); return x} // log every request, even failed ones
.retry(3) // Flaky server/connection, and I really need this data
return result
}
@inject(getDataFromAuthuserWith3Retrys)
function name2UpperReq(req) {
return getDataFromAuthuserWith3Retrys(req).map((x) =>{ x.name.toUpperCase(), return x}
}
@inject(name2UpperReq)
function someUsersService() {
name2UpperReq.subscribe(updateModel,handleError)
function updateModel(response) {
...
}
}
I know that there is a lot to improve in this sample, but I really think that if you want to do the same thing using promises, your code becomes larger, and more complex as this. And this is for a simple http json request, not even for a multiple provider.
Regards
Sander
--
You received this message because you are subscribed to the Google Groups "angular-data-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular-data-d...@googlegroups.com.
To post to this group, send email to angular-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/angular-data-dev/71234055-da42-4225-8458-360973889e7a%40googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "angular-data-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular-data-d...@googlegroups.com.
To post to this group, send email to angular-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/angular-data-dev/b381edbb-38e9-431f-a4e7-0cb9cb49ff5b%40googlegroups.com.
Observable.fromEvent(input, 'keypress').throttle(300).map(() => input.value).flatMapLatest(q => http('http://search/endpoint?q=' + q)).subscribe(showResults);
To view this discussion on the web visit https://groups.google.com/d/msgid/angular-data-dev/CAOTbQj0ZVyR%2BqQCgSzXUNqZx2b3gG_APVABzVzN3PmAirkFv0g%40mail.gmail.com.
Folks let's not forget that 99.9% of average usage is not that complicated. No retry. No cancellation. Just ask the server for something and await a response.
And cancellation w/ promises is already well understood as one of the flavors of promise rejection. That's how jQuery.ajax does it. That's how $http does it in v.1.
I love the observables. And if you want to get rid of interceptors, that's cool too. But we need a dead simple approach for the usual expectation that a request will be fulfilled once with either a successful result or a rejection+reason.
A `toPromise` feature sounds good to me.
That isn't what most of the world is doing. I don't know of any mainstream Angular tutorials, produced by the Angular team or anyone else, that feature a retry. We have numerous customers with Angular apps; to my knowledge, none of them issue a retry.
I hasten to add that all of the apps I've referenced target desktop browser usage where the probability of connectivity is very high and the likelihood is near zero that a retry would do any good at all when the connection fails.
>That reminds me: we'd be wise to create retry logic that only bothers to retry for known appropriate causes (e.g., timeout and lost connectivity), not for every cause.
I don't agree that canceling pending requests should be a required side-effect of view navigation (although that may be appropriate in some cases). Cancellation has no effect on what the server does and whether it is beneficial on the client-side is entirely application specific. For example, if I have a data service that maintains an entity cache and I issue a save request, I want that request to finish (if possible) regardless of where the user goes. I may need the response to update the cache (e.g, the store-generated primary keys for new records). Cancellation could leave the cache in a corrupt state.
I agree that handling cancellation on the rejection path is not a *great* idea. But it's not a *terrible* idea either, it works, and it's a common practice.
Finally, I reiterate that most of these requests ... these push requests ... will only ever have a single response. It's another mental hurdle for the developer to have to code for multiple responses when that isn't going to happen.
Sure we should be teaching what WE think are "better" practices. But you may recall the outrage when it seemed that Ng2 and the Ng team were only interested in foisting its notion of "a better way" on the community. They were too cavalier about the concerns of existing Ng developers with substantial existing investments in Ng. We want to encourage people to port their existing ng v.1 apps to ng2. We succeed in part when we impose as few changes as necessary and provide plenty of bridges. There are obstacles enough already; we don't need more of them.
@inject(httpObservable)
function(url){
return httpObservable(url).toPromise()
}
I repeat to be clear. I'm in favor of observables. I'm in favor of teaching the advantages of observables. But I'm reminding us of our responsibility to the community as it is today and urging a modicum of humility along the way.
End of rant. :-)
Benjamin:
jhusain:> Remember that jQuery got by with a collection-based API, which developers regularly used even when retrieving a single value by ID. I think that this example is pretty strong evidence that the average developer will not have difficulty getting their head around an entirely vector-based approach to asynchronous values.That's actually a point against observables. jQuery took a bad abstraction for selections (a live List) and instead worked with a useful abstraction which was conceptually representative better - a selection _set_. Developers did not have difficulty getting their head around it because it was inherently _simpler_. This is definitely not the case here imo.
No, the point was, that it’s easy to convert from single results (document.getElementById('someId')
) , to result sets ($('#someId')
). And people had no problem adapting it. I think this is a fair comparison.
Sander:> Example with expressive APIThat API is nice because of RxJS, not because of the observable abstraction. That's just having a lot of useful methods on the API. If you check out promise libraries a lot of them have a lot of that. Things like retry should also arguably be part of the $http core itself. I'm not sure the best way is to 'withdraw more things'.
That api is only possible because of the observables. Those are the key factor to enable this. If those where not provided by RX, it’s not that hard to provide them yourself. Show me how to do the same thing with promises, with the same amount of code. BTW, I used filter and map, I’m pretty sure those will be provided by default in ES7. And that’s it, the rest is just composition, enabled by observables.
blesh:> Now imagine that promise was received from a source that you could no longer call, and you wanted to cancel or retry it. You can't.That gives you the ability to separate capabilities. You can give someone the ability to cancel or retry your API, or you can decide you don't want them to have that ability. That's a good thing.
Show me some code that can do this with promises, and still is as terse and concise as the observables solution. Oh, and if you want, you can take the ability to cancel or retry away with observables too. Even when it is a bad idea to begin with. If you really want, you can enforce this separation. That does not make it a good idea for an communication layer!
> Angular 2 allows you to inject whatever you like, and you can inject promise-based http abstractions all you like if you strongly feel Promises are better. Or if you like, you can simply use `.toPromise()` and convert it to whatever promise impl you like: `myObservable.toPromise(RSVP.Promise)`.The problem is `.toPromise` does the wrong thing (TM) most of the time since it gets the last value and not all the values from the observable. Also from the same logic Angular 2.0 lets you import RxJS and consume promises with it just fine.
If I recall correctly you proclaimed that simple http calls should yield a promise. Well, simple http calls will allways yield to a single result (or none) so wrapping this single result to a promise does not comply how?
Even if we mix primitives:- Promises represent already started operations and are thus eager - observables are mostly lazy. While this isn't an inherent part of promises, in practice promise libraries do this. I like laziness better - what do you think users will enjoy more?
Ok, so for promises we should use a library to enable laziness, and for observables we only can’t use a library(RX as you noted above!) otherwise we make the API to easy? Did I get that right :-P
On a serious note, laziness is the way to go if you want to keep your performance high.
- Promises are immutable and can be consumed at any point - observables are (mostly) consumed once which I find nicer for this API and it also makes cancellation simpler since people don't expect subscription that's late to always work.
Promises have their place. But in communication settings observables make just a way better API. A part of that API should be, return a promise. For those things you want/need to cache/memorize.
Regards
Sander
We could end this whole discussion by aliasing `.subscribe()` as `.then()` and telling the promise diehards they won.
We could end this whole discussion by aliasing `.subscribe()` as `.then()` and telling the promise diehards they won.
> There is no more overhead in mixing promises and observables than there is in mixing numbers and arrays of numbers
When switching between promises and observables, there will be additional object allocations, closures, and next frame executions. Those are indeed more overhead.
Promise cancellation is usually ugly, and there are no standards around them. I've seen token based implementations. Impls that required a call to finally to trigger their start. Impls that require functions to be composed and passed down the promise chain.
Can you retry a promise? Sort of, not really. Not without doing some hacky, sketchy stuff. At that point, it's not a promise, it's a promise with a whole bunch of other code around it.
It's just not what they're designed for. If you need cancellation and retry, use an observable of one.
I'm not saying promises are horrible and you shouldn't use them. But they're a less useful abstraction for many use cases.
If you really like promise, then you can always call toPromise() on the Observable.
--
You received this message because you are subscribed to the Google Groups "angular-data-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular-data-d...@googlegroups.com.
To post to this group, send email to angular-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/angular-data-dev/1cc872ad-1d02-4c5e-87c6-68f734f7b0b9%40googlegroups.com.
Iterator of promise is equally a thumbs down. Too many allocations, to slow, less useful. The TC39 is a smart group of people, so I sincerely doubt they'd go that route. I'd be shocked if they did, really.
To view this discussion on the web visit https://groups.google.com/d/msgid/angular-data-dev/CADcN1GAkrtD0%2Bc35NhOeXbRKf3Wb1fG-XhMX4m9u%2BOh_Tbow3w%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/angular-data-dev/CADcN1GCMA1Py5rx_r1%3DuUKT%3Dby5cTmCe%3DHDKob674FzVYaw3CA%40mail.gmail.com.
I guess I can no longer tell what point is trying to be made. What is your position, Benjamin? If you were to "win" this argument, what would be the "win conditions"?