how to handle these function in a more idiomatic rxjs way - rxjs

I am new to rxjs (the project is stuck on rxjs 5 for the time being) and I don't really need to refactor sthese functions but as I'm trying to get up to speed with rxjs, how would I not use toPromise for an http call:
try {
const response = await this.http.post(`${TokenUrl}`, payload, options).toPromise();
} catch(err) {
// whatever
}
I also have this setInterval that periodically pings a server:
this.timerId = setInterval(() => {
this.blobStorageService.ping();
}, 60000);
I tried using interal but could not quite get the syntax right.

Related

Async/Await to simulate busy server that delay update to client browser

MERN noob here. Trying to learn Async/Await by simulating a busy server where client browser only get the update > 3 seconds later (i will manually refresh localhost:3000, after 3 seconds. I only need help on Node.js/ server side for this question)
Could you help rectify codes below? Kindly avoid proposing other ways/methods but show me how to achieve using below example. Thanks in advance.
const app = require('express')()
async function getData() {
//Purpose: to simulate a busy server that returns data back to browser, after 3 seconds delay
await setTimeout(() => {
return 'After waiting 3 seconds, return this sentense as the required data to the browser.'
}, 3000);
}
app.get('/', async (req, res) => {
try {
const data = await getData()
await res.status(200).send(`${data}`)
} catch (err) {
await res.status(400).send(`Unable to get data. Error message, "${err}"`)
}
})
app.listen(3000)
The problem here is that setTimeout doesn't return a promise so you can't use await with it. It just executes the given function after 3 seconds. You can get what you want by wrapping it in a Promise like this:
const app = require('express')()
function getData() {
//Purpose: to simulate a busy server that returns data back to browser, after 3 seconds delay
return new Promise((resolve) => {
setTimeout(() => {
resolve('After waiting 3 seconds, return this sentense as the required data to the browser.');
}, 3000);
});
}
app.get('/', async (req, res) => {
try {
const data = await getData()
await res.status(200).send(`${data}`)
} catch (err) {
await res.status(400).send(`Unable to get data. Error message, "${err}"`)
}
})
app.listen(3008)
Note that you need a return statement to return the promise inside of getData. You didn't have a return statement originally which means the function returns undefined (or if marked as async it gives a Promise that resolves to undefined).
Here we don't need to use async/await because you're not needing to use await until in the app.get. Using async/await in getData could be added but it would be redundant.
Realize that aync/await uses Promises - it's just an easy way to work with Promises. So you can't await on anything but a Promise. Note that async really just means "this function returns a Promise and we'll wrap any result in a Promise if it isn't already a Promise". So you cannot use async/await without having a Promise at some point.
But if you really want to use async/await for some reason maybe this example would help you:
async function getData() {
//Purpose: to simulate a busy server that returns data back to browser, after 3 seconds delay
const result = await new Promise((resolve) => {
setTimeout(() => {
resolve('After waiting 3 seconds, return this sentense as the required data to the browser.');
}, 3000);
});
console.log('We are done waiting 3 seconds');
return result; // <-- this returns a Promise that resolves to the result string
}

Transform RxJs Observable of Observables into count of how many Observables are pending?

I'm making a service that has multiple methods triggering HTTP calls. I want to reveal an Observable to clients that tells them whether there are any pending calls.
I think this approach would generally would work, but feels hacky and not very RxJs-like. I've searched all over StackOverflow and through the RxJs docs, but can't find a better way. Any advice? Thanks!
let pendingCountSubject = new BehaviorSubject<number>(0);
let pendingCount$ = pendingCountSubject.asObservable();
let pendingSubject = new Subject<Observable<any>>();
pendingSubject.pipe(
finalize(() => {
pendingCountSubject.next(pendingCountSubject.value - 1);
}))
.subscribe();
function trackPendingObservable(obs) {
pendingCountSubject.next(pendingCountSubject.value + 1);
pendingSubject.next(obs);
}
trackPendingObservable(httpCall1);
trackPendingObservable(httpCall2);
trackPendingObservable(httpCall3);
And in template:
Pending calls: {{ pendingCount$ | async }}
If I get it right, your service has several methods that perform http calls, e.g.
httpCall1(): Observable<any> { // do stuff}
httpCall2(): Observable<any> { // do stuff}
httpCallN(): Observable<any> { // do stuff}
Somehow these methods run in parallel, maybe because they are called in a rapid synchronous sequence.
What you want to show is how many of them are "on fly" at a certain moment.
Something like this may work.
The service exposes the http call methods as well as a counter of the calls currently "on fly".
export class MyHttpService {
constructor(private http: HttpClient)
public callsOnFly = 0;
httpGenericCall(httpCall: Observable<any>) {
this.callsOnFly++;
return httpCall
.pipe(
finalize(() => this.callsOnFly--)
)
}
httpCall1() {
return this.httpGenericCall(this.http.get('http://my-server1'));
}
httpCall12() {
return this.httpGenericCall(this.http.get('http://my-server2'));
}
httpCallN() {
return this.httpGenericCall(this.http.get('http://my-serverN'));
}
}
The component can just display via interpolation the value of the counter
Pending calls: {{ httpService.callsOnFly }}
where I assume that the name of MyHttpService in the component is httpService

How fast / efficient is Bluebird's timeout?

The following example times out in most cases (outputs timed out):
Promise = require('bluebird');
new Promise(resolve => {
setTimeout(resolve, 1000);
})
.timeout(1001)
.then(() => {
console.log('finished');
})
.catch(error => {
if (error instanceof Promise.TimeoutError) {
console.log('timed out');
} else {
console.log('other error');
}
});
Does this mean that the Bluebird's promise overhead takes longer than 1ms?
I see it often time out even if I use .timeout(1002).
The main reason for asking - I'm trying to figure what the safe threshold is, which gets more important with smaller timeouts.
Using Bluebird 3.5.0, under Node.js 8.1.2
I have traced your bug in Bluebird's code. Consider this:
const p = new Promise(resolve => setTimeout(resolve, 1000));
const q = p.timeout(1001); // Bluebird spawns setTimeout(fn, 1001) deep inside
That looks rather innocent, yeah? Though, not in this case. Internally, Bluebird implemented it something like (not actually valid JS; timeout clearing logic is omitted):
Promise.prototype.timeout = function(ms) {
const original = this;
let result = original.then(); // Looks like noop
setTimeout(() => {
if result.isPending() {
make result rejected with TimeoutError; // Pseudocode
}
}, ms);
return result;
}
Bug was presence of line ret.isPending(). It resulted in brief time when original.isPending() === false and ret.isPending() === true because "resolved" status didn't propagate yet from original to children. Your code hit that extremely short period and BOOM, you had race condition.
I think what's going on here is that there's a race between the time the rest of the promise chain takes and the timer from the .timeout(). Since they are both so close in timing, sometimes one wins and sometimes the other wins - they are racy. When I run this code that logs the sequence of events, I get different ordering on different runs. The exact output order is unpredictable (e.g. racy).
const Promise = require('bluebird');
let buffer = [];
function log(x) {
buffer.push(x);
}
new Promise(resolve => {
setTimeout(() => {
log("hit my timeout");
resolve();
}, 1000);
}).timeout(1001).then(() => {
log('finished');
}).catch(error => {
if (error instanceof Promise.TimeoutError) {
log('timed out');
} else {
log('other error');
}
});
setTimeout(() => {
console.log(buffer.join("\n"));
}, 2000);
Sometimes this outputs:
hit my timeout
finished
And, sometimes it outputs:
hit my timeout
timed out
As has been mentioned in the comments, if .then() was always executed via microtask (which should precede any macrotasks), then one would think that the .then() would precede the setTimeout() from the .timeout(), but things are apparently not that simple.
Since the details of promise .then() scheduling is not mandated by specification (only that the stack is clear of application code) a code design should not assume a specific scheduling algorithm. Thus, a timeout this close to the execution of the async operation it is following can be racy and thus unpredictable.
If you could explain exactly what problem you're trying to solve, we could probably offer more concrete advice about what to do. No timers in Javascript are precise to the ms because JS is single threaded and all timer events have to go through the event queue and they only call their callbacks when their event gets serviced (not exactly when the timer fired). That said, timer events will always be served in order so a setTimeout(..., 1000) will always come before setTimeout(..., 1001), even though there may not be exactly 1ms delta between the executing of the two callbacks.

How to mock an ajax call in mocha using sinon without setting timeout on a ractive component using reflux store

I have a working ractive component test case already with mocha using sinon ans able to mock an ajax call but with the help of setTimeout(function(){}, 100) and I dont like using it.
beforeEach(function () {
this.container = document.createElement('div');
document.body.appendChild(this.container);
this.server = sinon.fakeServer.create();
this.server.respondWith(
"GET",
"/api/url",
[
200,
{ "Content-Type": "application/json" },
'{"data": []}'
]
);
});
afterEach(function () {
document.body.removeChild(this.container);
});
it("should fetch data from server", function (done) {
var server = this.server;
var Component = require('rvc!path/to/component');
var component = new Component({
el: this.container,
});
setTimeout( function() {
server.respond();
expect(component.findAll('.list li').length).to.equal(7);
done();
}, 100);
});
As you can see in the code above, I'm using the setTimeout to make sure that the ajax call (mock) was made before having the actual test of the component.
Is there a way that I can eliminate the setTimeout having the same effect? Thanks!
Assuming that your http request is happening in the component, then it won't get the data until the next tick of the event loop.
One approach is to use setTimeout as you have done, but you probably can lower the timeout (use autoRespondAfter to adjust the sinon response delay).
If your component code supports it, an approach that seems well suited to your use case from the sinon fakeServer docs would be to use the respondImmediately option:
If set, the server will respond to every request immediately and
synchronously. This is ideal for faking the server from within a test
without having to call server.respond() after each request made in
that test. As this is synchronous and immediate, this is not suitable
for simulating actual network latency in tests or mockups.
this.server = sinon.fakeServer.create({ respondImmediately: true })
// now no need to call server.respond() and calls are returned synchronously!

Bacon.retry not retrying on 'Access-Control-Allow-Origin' errors

I have a buggy Web service that sporadically sends a 500-error "XMLHttpRequest cannot load http://54.175.3.41:3124/solve. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://local.xxx.me:8080' is therefore not allowed access. The response had HTTP status code 500."
I use Bacon.retry to wrap the ajax call. When it fails, it'll just retry. However, what I notice is that the stream won't produce a value when the server fails. It's as if Bacon.retry doesn't retry (which is in fact what's happening, when I look under the hood in the dev console).
I'm using BaconJS 0.7.65.
The observable Bacon.retry looks like this:
var ajaxRequest = Bacon.fromPromise($.ajax(//...));
var observable = Bacon.retry({
source: function() { return ajaxRequest; },
retries: 50,
delay: function() { return 100; }
});
The code that calls the observable looks like this:
stream.flatMap(function(valuesOrObservables) {
return Bacon.fromArray(valuesOrObservables)
.flatMapConcat(function(valueOrObservable) {
switch(valueOrObservable.type) { //we calculate this beforehand
case 'value' :
return valueOrObservable.value;
case 'observable' :
return Bacon.fromArray(valueOrObservable.observables)
.flatMapConcat(function(obs) { return obs; })
}
})
})
Observations:
if I add an error handler to the observable, it still does not work.
for some reason, #retry is called 50 times even when it succeeds.
I'm not sure entirely about Bacon but in RxJS Ajax calls are usually wrapped around AsyncSubjects so re subscribing to an error'd stream will just fire off the same error, you generally have to re-execute the method that produces the observable.
So something like retry would be (again sorry this is in Rx):
Rx.Observable.defer(() => callAjaxReturnObservable())
.retry(50)
.subscribe();
EDIT 1
Trying Baconize this and clarify my earlier answer:
var observable = Bacon.retry({
source : function() { return Bacon.fromPromise($.ajax(/**/)); },
retries : 50,
delay: function() { return 100; }
});
If you don't have the fromPromise inside of the source function, then every time you retry the downstream will just receive the same exception.

Resources