I presume this is a basic mistake, but as my searches made no effect, let's do it here anyway :)
I have a function returning a promise, but it runs so fast (because code is almost empty) that when .then() is called, it is too late and no event is called.
The reason why it happens is because that's a dummy code (for testing), so, the Promise concept is applied because of a situation where an actual async request is done.
So, is there a way to call the resolve/reject functions even after the function was processed? Or I would have to use lazy promises?
Update: I tried RSVP.defer() but didn't like its approach as it's not intuitive enough (requires some workaround to set .then() and .catch(), etc.
I have a function returning a promise, but it runs so fast (because code is almost empty) that when .then() is called, it is too late and no event is called.
That does not matter even one bit. Well behaved promises (like native promises, and virtually every library except old jQuery) are built with a guarantee that no matter when you attach the then handler - it will call the handler (and it will always do so asynchronously). A promise is just a value + time.
RSVP passes a suite of over 1000 tests to ensure this is always the case.
var p = Promise.resolve(); // create empty, already resolved promise
setTimeout(function(){
p.then(function(){
// will always be called, eventually.
});
}, 1000000 + Math.random() * 10000000);
Related
I am using the following code to basically ensure that I get a result from an Observable
this.authenticationService.isLoggedIn
.pipe(
take(1),
defaultIfEmpty(false)
)
.subscribe(result => return result);
Somehow it feels wrong to me, maybe because it seems sort of procedural.
Is this method okay? Will this get me in trouble in any way?
If in your code it's fine that this.authenticationService.isLoggedIn completes without an emit - then the code in your question is fine too.
If this.authenticationService.isLoggedIn emits anything at some point of time and completes after - then defaultIfEmpty is redundant.
It all depends on what isLoggedIn does.
It is clear that isLoggedIn returns an Observable.
Now, and Observable can do just 3 things
it can notify, i.e. emit, some data for consumption of Observers which are subscribed
it can raise an error
it can complete
So the first question is: how many times can isLoggedIn notify? Is it just one shot or is it a stream of notifications? If it can emit just one value and then complete, than the take(1) operator is useless.
But there is also the case that isLoggedIn never notifies and just completes. In this case a notification would never be signaled by the observer to its subscriber. Using defaultIfEmpty operator ensures that something is notified even in this case.
So, reading your code I understand that isLoggedIn can behave in these 2 ways
Emit more than once but you are interested only in the first notification
Never notify and just complete, in which case you want false to be returned
If this is not true, it may be the case that your code can be simplified.
I have seen three different patterns for this and the alt docs do not make the distinction clear. If I have an action, how should I go about calling dispatch? Here are the three ways I have seen:
1. The action returns a function, which `dispatch` is passed into.
addPayment(args) {
return (dispatch) => {
dispatch();
// other action code
};
}
2. The action calls this.dispatch.
addPayment(args) {
this.dispatch();
// other action code
}
3. The action does not call dispatch.
addPayment(args) {
// other action code
}
It is not clear to me what difference there is between these three options, and it is especially unclear to me whether option #3 calls dispatch at all.
The bindActions method seems to associate actions with action handlers, so it would kind of make sense that a given action handler should be called automatically when the associated action is called, which would result in code that looked like option #3. But then, why would we ever need to explicitly call dispatch?
There is no tag for alt, so....yeah. Tagging it flux since that's the closest match.
Okay, as I understand things, approach #2 was patched out in later releases of alt and will now cause an error.
Approach #1 works fine when you want to trigger dispatch before your action completes. It's generally used when you have a handler that initiates a loading state in the UI, so you want to set things to loading while your action completes. Then you have separate success/failure actions (often just generated via alt's generateActions) with their own handlers which take care of what happens after the action completes.
Approach #3 is for when you want to trigger dispatch after your action completes. Here's a key bit from the alt docs that I missed:
You can also simply return a value from an action to dispatch.
So simply returning a value will call dispatch, and thus your action completes first. The docs also hasten to add:
There are two exceptions to this, however:
Returning false or undefined (or omitting return altogether) will not dispatch the action
Returning a Promise will not dispatch the action
So that bit provides a way to avoid triggering dispatch at all.
Xamarin.Forms.Device.StartTimer is a convenient method to repeatedly call some code in a certain interval. This is similar to JavaScript's SetInverval() method. JavaScript also has a method to set a single delay, called SetTimeout() - it delays a certain amount of time, then calls the callback code once. Is there a SetTimeout equivalent for Xamarin.Forms, where I simply want the code to be called in the background after a certain delay?
NOTE: I know I can return false to stop the recurrence, and that's easy enough. It just seems like if you're only intending to call the callback once, it's a little semantically misleading to use this recurring timer mechanism.
StartTimer will do this
While the callback returns true, the timer will keep recurring.
Simply return false to stop the timer
You could start a Task with delay:
async Task DoSomethingOnceWithDelay(TimeSpan delay)
{
await Task.Delay(delay);
await MyTask();
}
Official doc.
Should I unsubscribe on every ajax call? According to the RxJS contract, I should. Because AJAX calls are not streams or events, once they are done they are done. What is the reason of using RxJS at all in this particular case? Overtime it becomes the mess (I know about takeUntil, that's not the point here).
public remove(data: IData): void {
// unsubscribe from the previous possible call
if (this.dataSubscription &&
this.dataSubscription.unsubscribe) {
this.dataSubscription.unsubscribe();
}
this.dataSubscription = this.dataService
.delete(data.id)
.subscribe(() => {
this.refresh();
});
}
public ngOnDestroy(): void {
// unsubscribe on deletion
if (this.dataSubscription &&
this.dataSubscription.unsubscribe) {
this.dataSubscription.unsubscribe();
}
}
What is the advantage over simple promise, that looks cleaner and destroyed right after execution?
public remove(data: IData): void {
this.dataService
.delete(data.id)
.then(() => {
this.refresh();
});
}
This is DataService code
#Injectable()
export class DataService {
constructor(private _httpClient: HttpClient) { }
public delete(id: number): Observable<IModel> {
return this._httpClient.delete<IModel>(`${this._entityApiUrl}/${id}`);
}
}
Finite, cold Observables usually don't need to be unsubscribed. They work just like Promises in this regard. Assuming you're using Angular's HttpClient in your service, no unsubscription is necessary--it's much like a Promise in that situation.
First off, to clear some things up -- in your Promise example, you are imperatively managing the Promise by assigning it to this.dataSubscription. After that call is made, anything that calls this.dataSubscription.then() an arbitrary amount of time after the HTTP call will receive a Promise.resolve() and invoke that .then() function. The new Promise returned by Promise.resolve() will be cleaned up after it executes, but it's only until your class is destroyed that your this.dataSubscription Promise will be cleaned up.
However, not assigning that Promise as a property is even cleaner:
public remove(data: IData): void {
this.dataService
.delete(data.id)
.then(() => {
this.refresh();
});
}
plus, the Promise will be cleaned up at the end of its scope, not on the destruction of the class.
Observables, at least finite 'Promise-like' ones like this, work in much the same way. You don't need to manage the Subscription returned buy the .subscribe() method imperitavely, as it will execute and then be cleaned up as it's not assigned as a property:
public remove(data: IData): void {
this.dataService
.delete(data.id)
.subscribe(() => {
this.refresh();
});
}
It's a finite Observable and completes after the subscription, so calling subscribe again will return a new Subscription and re-call the Observable's function.
Imperitavely managing those subscriptions is indeed messy and usually a sign things could be done better.
The difference with RXJS's subscription management is that RXJS can become an incredibly powerful tool, one that is useful for way, way more than managing async AJAX calls. You can have hot Observables that publish data to hundreds of subscribers, Subjects that manage their own stream to many subscribers, infinite Observables that never stop emitting, higher-order Observables that manage state and return other Observables, etc. In this case unsubscribing is best practice, but honestly not going to cause performance issues outside of extreme cases.
A good comparison is the Observable.fromEvent() property. Just like it's best practice to use removeEventListener correctly after addEventListener, you should unsubscribe from this Observable correctly. However, just like removeEventListener,...it's not really done all the time and usually doesn't cause issues with today's platforms.
Also, in reference to the 'RxJS contract' that was stated: here's an excerpt from the same doc:
When an Observable issues an OnError or OnComplete notification to its observers, this ends the subscription. Observers do not need to issue an Unsubscribe notification to end subscriptions that are ended by the Observable in this way.
Finite Observables complete themselves after their emissions and don't need to be unsubscribed.
Usually you don't need to unsubscribe from HttpClient calls since all HttpClient calls complete the stream once they receive response from the server. Once an observable stream completes or errors, its the responsibility of the producer to release resources. For more information, read Insider’s guide into interceptors and HttpClient mechanics in Angular. You should unsubscribe only if you want to cancel the request.
Because AJAX calls are not streams or events, once they are done they are done... What is the advantage over simple promise, that looks cleaner and
destroyed right after execution?
AJAX calls are not just one time event. For example, you can have multiple progress events with XHR. Promise resolves with only one value, while HttpClient can emit multiple HTTP events:
export type HttpEvent<T> =
HttpSentEvent | HttpHeaderResponse | HttpResponse<T>| HttpProgressEvent | HttpUserEvent<T>
You don't need to unsubscribe on every ajax call. But then you are losing one of the core benefits of Observables - being able to cancel it.
You really need to think about what your code does and what is your standard workflow. What happens if the delete response takes a long time and user clicks it again, or clicks back, or goes to some other page?
Would you like refresh to still happen (since observable will still keep the callback in the memory) or would you rather cancel it?
It's up to you and your application at the end. By using unsubscribe you save yourself from unplanned side effects.
In your case, it's just a refresh so it's not a big deal. Then again, you will keep it in the memory and it might cause some side effects.
I am new to angular and want to use it to send data to my app's backend. In several occasions, I have to make several http post calls that should either all succeed or all fail. This is the scenario that's causing me a headache: given two http post calls, what if one call succeeds, but the other fails? This will lead to inconsistencies in the database. I want to know if there's a way to cancel the succeeding calls if at least one call has failed. Thanks!
Without knowing more about your specific situation I would urge you to use the promise error handling if you are not already doing so. There's only one situation that I know you can cancel a promise that has been sent is by using the timeout option in the $http(look at this SO post), but you can definitely prevent future requests. What happens when you make a $http call is that it returns a promise object(look at $q here). What this does is it returns two methods that you can chain on your $http request called success and failure so it looks like $http.success({...stuff...}).error({...more stuff..}). So if you do have error handling in each of these scenarios and you get a .error, dont make the next call.
You can cancel the next requests in the chain, but the previous ones have already been sent. You need to provide the necessary backend functionality to reverse them.
If every step is dependent on the other and causes changes in your database, it might be better to do the whole process in the backend, triggered by a single "POST" request. I think it is easier to model this process synchronously, and that is easier to do in the server than in the client.
However, if you must do the post requests in the client side, you could define each request step as a separate function, and chain them via then(successCallback, errorCallback) (Nice video example here: https://egghead.io/lessons/angularjs-chained-promises).
In your case, at each step you can check if the previous one failed an take action to reverse it by using the error callback of then:
var firstStep = function(initialData){
return $http.post('/some/url', data).then(function(dataFromServer){
// Do something with the data
return {
dataNeededByNextStep: processedData,
dataNeededToReverseThisStep: moreData
}
});
};
var secondStep = function(dataFromPreviousStep){
return $http.post('/some/other/url', data).then(function(dataFromServer){
// Do something with the data
return {
dataNeededByNextStep: processedData,
dataNeededToReverseThisStep: moreData
}
}, function(){
// On error
reversePreviousStep(dataFromPreviousStep.dataNeededToReverseThisStep);
});
};
var thirdFunction = function(){ ... };
...
firstFunction(initialData).then(secondFunction)
.then(thirdFunction)
...
If any of the steps in the chain fails, it's promise would fail, and next steps will not be executed.