Similar to Get first fulfilled promise but in RxJS
If I have two promises A and B, only one of which will succeed, how can I get whichever one fulfills successfully? Some of the promises will have rejection as well. Only the successful promise is needed.
I'm looking for something similar to Promise.race, but which will return only the first promise that fulfills. I'm using promises from RxJS6.
RxJS has race also:
import {race} from 'rxjs'
race(promiseA, promiseB).subscribe(result => console.log('winner is ' + result))
Related
I’d like to await the completion of my observable. It has a takeUntil I receive a value emited from my cancel$ observable. Its possible that cancel$ emits a valeu befor observable1 even emits its first value. That will give me an error.
await lastValueFrom(observable1.pipe(takeUntil(cancel$)))
console.log("myObservable is completed");
I found that using the deprecated await observable1.toPromise() fixes my problem. But I'd like to avoid something deprecated.
Ok, I finally found my answer here : .toPromise() and lastValueFrom() in rxjs
lastValueFrom takes a second parameter where you can define a default value when nothing has been emitted.
Is it ok to write:
getFieldX().clear().sendKeys('abc');
or should I write:
getFieldX().clear().then( () => sendKeys('abc));
I'm totally confused about the Promise handling in protractor. clear() returns a promise, so I should use .then() afterwards, shouldn't I?
But I found examples with .then and some without.
Protractor itself has an example without .then():
https://www.protractortest.org/#/control-flow
Does Protractor has its own mechanism and resolves one after the other promise so there is no need for using .then() after a protractor call that returns a Promise?
And is the control flow of protractor only active in a spec?
When using .sendKeys() in a normal function I have to use .sendKeys().then(...) ?
This all depends on if you are using SELENIUM_PROMISE_MANAGER or not. As this is (has?) becoming deprecated, I would not use it. It should be set to false by default, but if you want to be sure you can add SELENIUM_PROMISE_MANAGER = false; to your conf file. The way that protractor has been moving is to use async/await, so your sendKeys function would look like:
let field = element(by.css('CSS.Selector'));
await field.clear();
await field.sendKeys('abc');
Because these are async functions, you will need to define your function properly, so a basic spec would look like:
describe('Demonstrating async/await',function(){
it('Should send some keys', async function(){
let field = element(by.css('CSS.Selector'));
await field.clear();
await field.sendKeys('abc');
});
});
The important difference there is that a function needs to be defined as async function(). As far as reading the code goes, await simply can be read as "Wait until promise resolved to move on". It does get a bit tedious and you feel like you write await before every line of code (you basically do), but I find it significantly better than .then() trees.
I setup a subject and then put some methods on it. It seems to work as intended until it gets to .switch() which I thought would simply keep track of the last call. I get the error Property 'subscribe' does not exist on type 'ApiChange' It seems to convert it to type ApiChange from an observable. I don't understand this behavior. Should I be using a different operator?
Service:
private apiChange = new Subject<ApiChange>();
apiChange$ = this.apiChange.asObservable().distinctUntilChanged().debounceTime(1000).switch();
Component:
this.service.apiChange$.subscribe(change => {
this.service.method(change);
});
.debounceTime(1000) will already assure you will only get a maximum of one value emitted from your observable chain per second. All the values preceding the 1 second quiet time will already be discarded.
With a simple Subject (not a ReplaySubject), past values are not provided to subscribers anyway.
You probably just want to skip the .switch() and enjoy the chain without it.
I'm going a little nuts working with Volt at the moment. The moment I try to do something a bit more complicated I end up getting the exception "ArgumentError: a promise has already been chained" in the browser console.
The stack trace doesn't point to anything I can interpret as useful.
That does this error actually mean, and how do I go about trying to track down the cause?
I'd post some code, but some of these errors appear on page load with no indication of where the problem is, so I'd need to post the entire app :/
Volt uses Opal's promise implementation, which I believe is based on the A+ spec in JS land. The error your seeing is because a promise can only have a single .then or .fail block on it. Each .then or .fail will return a new promise that you can then chain off of.
So you can do this:
promise = Promise.new
promise2 = promise.then do
..
end
promise2.then do
..
end
(notice I'm assigning promise2 instead of chaining off of the first one again)
But you can not do something like this:
promise = Promise.new
promise.then do
...
end
promise.then do
..
end
(Notice how I called .then on promise more than once)
A more compact way to write the first is to chain off of the end's
promise = Promise.new
promise.then do
..
end.then do
..
end.fail do
..
end
Volt bindings expect a promise that hasn't been chained on. Also, I think I can make it work where you can chain multiple times, though I haven't thought through all of the implications of this, so I could be wrong. If I get some time I might write a new promise implementation that can handle this. If your still seeing that error and the above doesn't explain why its there, let me know. Thanks!
I'm trying to use Q Promise implementation, but am facing strange inconsistency.
When I run in Chrome m33, the following code:
new Promise(function(resolve, reject) {
resolve(1);
}).then(function(value) {
console.log(value);
});
It works just as I expect - it returns another Promise and logs 1.
But if I call the same code wrapped into (function (Promise) { ... }(window.Q));, I see body of resolve callback in console, instead of a value.
Fiddle to look at - works in Chrome and Aurora.
Am I missing something or is it a bug in the library?
PS: Q version 1.0.0
It looks, like Q.promise is a replacement for native Promise, not the Q itself: fiddle.
It's very strange, though. I can't migrate to native promises w/o changing the code later.
Cause Q.promise -> Promise, but Q.all -> Promise.all.
Upgrade to Q v1.0.1 which introduces Q.Promise, which supports a common subset of the ES6 promise interface. Q is analogous to Promise.resolve and new Promise replaces the erstwhile Q.defer(). ES6 did not lift the Q API exactly, but did largely lift the behavior of the analogous functions.