How to turn multiple observables an observable that emits once when all the source observables complete?
I'm calling an API method (using Angular's HttpClient
several times as part of a form submission. (It adds a thing into another thing and our backend guys flat out refused to give me a batch-add method. So I call it once for every item the user enters.) The code is something like this (using lodash for data massaging):
const items = ['foo', 'bar', 'baz', 'quux'];
const result$: Observable = _.map(items, it => httpClient.post('/items', it));
I tried combining them using forkJoin
:
forkJoin(result$).subscribe(resp => ..., err => ...);
But that revealed some sort of bug in the back-end where it throws when I do this for multiple items, but doesn't if I add them one-by-one. (Race condition I'm guessing.)
I tried getting around this by using concat() to make the client do the requests one-by-one:
concat(result$).subscribe(resp => ..., err => ...);
But that fires the subscription once for every source observable, I only want to know when they all complete (or don't.) How do I get the behaviour of forkJoin, except with the source observables not being subscribed to concurrently?
javascript typescript rxjs
|
show 1 more comment
I'm calling an API method (using Angular's HttpClient
several times as part of a form submission. (It adds a thing into another thing and our backend guys flat out refused to give me a batch-add method. So I call it once for every item the user enters.) The code is something like this (using lodash for data massaging):
const items = ['foo', 'bar', 'baz', 'quux'];
const result$: Observable = _.map(items, it => httpClient.post('/items', it));
I tried combining them using forkJoin
:
forkJoin(result$).subscribe(resp => ..., err => ...);
But that revealed some sort of bug in the back-end where it throws when I do this for multiple items, but doesn't if I add them one-by-one. (Race condition I'm guessing.)
I tried getting around this by using concat() to make the client do the requests one-by-one:
concat(result$).subscribe(resp => ..., err => ...);
But that fires the subscription once for every source observable, I only want to know when they all complete (or don't.) How do I get the behaviour of forkJoin, except with the source observables not being subscribed to concurrently?
javascript typescript rxjs
1
concat(...).pipe(ignoreElements())
will either complete (but emit no values) or error.
– cartant
Nov 21 at 2:30
@cartant - well, that at least pointed me in the right direction, now I know I can pass acomplete
callback tosubscribe()
– millimoose
Nov 21 at 2:32
This reads like you already know the answer.
– Stefan Hanke
Nov 21 at 5:34
@StefanHanke - I’ll either answerify what I have or nule this question since it’s a pretty basic API thing and I also have an unrelated bug in the question code; I’ll decide after finishing this all-nighter and catching at least a little sleep
– millimoose
Nov 21 at 5:37
OT, but you should tell your backend guys that doing this one by one is not only a scaling issue (user needs to wait n times as long), but also an issue of transactionality (usually you want all to succeed or fail, not get an intermediate state) and atomicity (user leaves page mid-stream will execute only half the requests). Also, maybe if they don't give you the endpoint, they should at least fix that bug. Not serving an endpoint concurrently is outrageous. Your backend guys are wrong here, very wrong.
– Ingo Bürk
Nov 21 at 7:00
|
show 1 more comment
I'm calling an API method (using Angular's HttpClient
several times as part of a form submission. (It adds a thing into another thing and our backend guys flat out refused to give me a batch-add method. So I call it once for every item the user enters.) The code is something like this (using lodash for data massaging):
const items = ['foo', 'bar', 'baz', 'quux'];
const result$: Observable = _.map(items, it => httpClient.post('/items', it));
I tried combining them using forkJoin
:
forkJoin(result$).subscribe(resp => ..., err => ...);
But that revealed some sort of bug in the back-end where it throws when I do this for multiple items, but doesn't if I add them one-by-one. (Race condition I'm guessing.)
I tried getting around this by using concat() to make the client do the requests one-by-one:
concat(result$).subscribe(resp => ..., err => ...);
But that fires the subscription once for every source observable, I only want to know when they all complete (or don't.) How do I get the behaviour of forkJoin, except with the source observables not being subscribed to concurrently?
javascript typescript rxjs
I'm calling an API method (using Angular's HttpClient
several times as part of a form submission. (It adds a thing into another thing and our backend guys flat out refused to give me a batch-add method. So I call it once for every item the user enters.) The code is something like this (using lodash for data massaging):
const items = ['foo', 'bar', 'baz', 'quux'];
const result$: Observable = _.map(items, it => httpClient.post('/items', it));
I tried combining them using forkJoin
:
forkJoin(result$).subscribe(resp => ..., err => ...);
But that revealed some sort of bug in the back-end where it throws when I do this for multiple items, but doesn't if I add them one-by-one. (Race condition I'm guessing.)
I tried getting around this by using concat() to make the client do the requests one-by-one:
concat(result$).subscribe(resp => ..., err => ...);
But that fires the subscription once for every source observable, I only want to know when they all complete (or don't.) How do I get the behaviour of forkJoin, except with the source observables not being subscribed to concurrently?
javascript typescript rxjs
javascript typescript rxjs
asked Nov 21 at 2:17
millimoose
32.1k761102
32.1k761102
1
concat(...).pipe(ignoreElements())
will either complete (but emit no values) or error.
– cartant
Nov 21 at 2:30
@cartant - well, that at least pointed me in the right direction, now I know I can pass acomplete
callback tosubscribe()
– millimoose
Nov 21 at 2:32
This reads like you already know the answer.
– Stefan Hanke
Nov 21 at 5:34
@StefanHanke - I’ll either answerify what I have or nule this question since it’s a pretty basic API thing and I also have an unrelated bug in the question code; I’ll decide after finishing this all-nighter and catching at least a little sleep
– millimoose
Nov 21 at 5:37
OT, but you should tell your backend guys that doing this one by one is not only a scaling issue (user needs to wait n times as long), but also an issue of transactionality (usually you want all to succeed or fail, not get an intermediate state) and atomicity (user leaves page mid-stream will execute only half the requests). Also, maybe if they don't give you the endpoint, they should at least fix that bug. Not serving an endpoint concurrently is outrageous. Your backend guys are wrong here, very wrong.
– Ingo Bürk
Nov 21 at 7:00
|
show 1 more comment
1
concat(...).pipe(ignoreElements())
will either complete (but emit no values) or error.
– cartant
Nov 21 at 2:30
@cartant - well, that at least pointed me in the right direction, now I know I can pass acomplete
callback tosubscribe()
– millimoose
Nov 21 at 2:32
This reads like you already know the answer.
– Stefan Hanke
Nov 21 at 5:34
@StefanHanke - I’ll either answerify what I have or nule this question since it’s a pretty basic API thing and I also have an unrelated bug in the question code; I’ll decide after finishing this all-nighter and catching at least a little sleep
– millimoose
Nov 21 at 5:37
OT, but you should tell your backend guys that doing this one by one is not only a scaling issue (user needs to wait n times as long), but also an issue of transactionality (usually you want all to succeed or fail, not get an intermediate state) and atomicity (user leaves page mid-stream will execute only half the requests). Also, maybe if they don't give you the endpoint, they should at least fix that bug. Not serving an endpoint concurrently is outrageous. Your backend guys are wrong here, very wrong.
– Ingo Bürk
Nov 21 at 7:00
1
1
concat(...).pipe(ignoreElements())
will either complete (but emit no values) or error.– cartant
Nov 21 at 2:30
concat(...).pipe(ignoreElements())
will either complete (but emit no values) or error.– cartant
Nov 21 at 2:30
@cartant - well, that at least pointed me in the right direction, now I know I can pass a
complete
callback to subscribe()
– millimoose
Nov 21 at 2:32
@cartant - well, that at least pointed me in the right direction, now I know I can pass a
complete
callback to subscribe()
– millimoose
Nov 21 at 2:32
This reads like you already know the answer.
– Stefan Hanke
Nov 21 at 5:34
This reads like you already know the answer.
– Stefan Hanke
Nov 21 at 5:34
@StefanHanke - I’ll either answerify what I have or nule this question since it’s a pretty basic API thing and I also have an unrelated bug in the question code; I’ll decide after finishing this all-nighter and catching at least a little sleep
– millimoose
Nov 21 at 5:37
@StefanHanke - I’ll either answerify what I have or nule this question since it’s a pretty basic API thing and I also have an unrelated bug in the question code; I’ll decide after finishing this all-nighter and catching at least a little sleep
– millimoose
Nov 21 at 5:37
OT, but you should tell your backend guys that doing this one by one is not only a scaling issue (user needs to wait n times as long), but also an issue of transactionality (usually you want all to succeed or fail, not get an intermediate state) and atomicity (user leaves page mid-stream will execute only half the requests). Also, maybe if they don't give you the endpoint, they should at least fix that bug. Not serving an endpoint concurrently is outrageous. Your backend guys are wrong here, very wrong.
– Ingo Bürk
Nov 21 at 7:00
OT, but you should tell your backend guys that doing this one by one is not only a scaling issue (user needs to wait n times as long), but also an issue of transactionality (usually you want all to succeed or fail, not get an intermediate state) and atomicity (user leaves page mid-stream will execute only half the requests). Also, maybe if they don't give you the endpoint, they should at least fix that bug. Not serving an endpoint concurrently is outrageous. Your backend guys are wrong here, very wrong.
– Ingo Bürk
Nov 21 at 7:00
|
show 1 more comment
1 Answer
1
active
oldest
votes
You can use concatMap
concatMap: it's maping values to inner observable, subscribe and emit
in order.
In your case forkJoin
is doing all subscriptions at the same time, but concatMap
should do them one by one.
I hope this is useful to you
Sorry, no, concatMap still emits once for every time a source observable emits.
– millimoose
Nov 21 at 2:29
canskipUntil
help you here? rxjs-dev.firebaseapp.com/api/operators/skipUntil
– Microsmsm
Nov 21 at 2:41
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53404422%2fhow-to-turn-multiple-observables-an-observable-that-emits-once-when-all-the-sour%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use concatMap
concatMap: it's maping values to inner observable, subscribe and emit
in order.
In your case forkJoin
is doing all subscriptions at the same time, but concatMap
should do them one by one.
I hope this is useful to you
Sorry, no, concatMap still emits once for every time a source observable emits.
– millimoose
Nov 21 at 2:29
canskipUntil
help you here? rxjs-dev.firebaseapp.com/api/operators/skipUntil
– Microsmsm
Nov 21 at 2:41
add a comment |
You can use concatMap
concatMap: it's maping values to inner observable, subscribe and emit
in order.
In your case forkJoin
is doing all subscriptions at the same time, but concatMap
should do them one by one.
I hope this is useful to you
Sorry, no, concatMap still emits once for every time a source observable emits.
– millimoose
Nov 21 at 2:29
canskipUntil
help you here? rxjs-dev.firebaseapp.com/api/operators/skipUntil
– Microsmsm
Nov 21 at 2:41
add a comment |
You can use concatMap
concatMap: it's maping values to inner observable, subscribe and emit
in order.
In your case forkJoin
is doing all subscriptions at the same time, but concatMap
should do them one by one.
I hope this is useful to you
You can use concatMap
concatMap: it's maping values to inner observable, subscribe and emit
in order.
In your case forkJoin
is doing all subscriptions at the same time, but concatMap
should do them one by one.
I hope this is useful to you
answered Nov 21 at 2:28
Microsmsm
1,8851624
1,8851624
Sorry, no, concatMap still emits once for every time a source observable emits.
– millimoose
Nov 21 at 2:29
canskipUntil
help you here? rxjs-dev.firebaseapp.com/api/operators/skipUntil
– Microsmsm
Nov 21 at 2:41
add a comment |
Sorry, no, concatMap still emits once for every time a source observable emits.
– millimoose
Nov 21 at 2:29
canskipUntil
help you here? rxjs-dev.firebaseapp.com/api/operators/skipUntil
– Microsmsm
Nov 21 at 2:41
Sorry, no, concatMap still emits once for every time a source observable emits.
– millimoose
Nov 21 at 2:29
Sorry, no, concatMap still emits once for every time a source observable emits.
– millimoose
Nov 21 at 2:29
can
skipUntil
help you here? rxjs-dev.firebaseapp.com/api/operators/skipUntil– Microsmsm
Nov 21 at 2:41
can
skipUntil
help you here? rxjs-dev.firebaseapp.com/api/operators/skipUntil– Microsmsm
Nov 21 at 2:41
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53404422%2fhow-to-turn-multiple-observables-an-observable-that-emits-once-when-all-the-sour%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
concat(...).pipe(ignoreElements())
will either complete (but emit no values) or error.– cartant
Nov 21 at 2:30
@cartant - well, that at least pointed me in the right direction, now I know I can pass a
complete
callback tosubscribe()
– millimoose
Nov 21 at 2:32
This reads like you already know the answer.
– Stefan Hanke
Nov 21 at 5:34
@StefanHanke - I’ll either answerify what I have or nule this question since it’s a pretty basic API thing and I also have an unrelated bug in the question code; I’ll decide after finishing this all-nighter and catching at least a little sleep
– millimoose
Nov 21 at 5:37
OT, but you should tell your backend guys that doing this one by one is not only a scaling issue (user needs to wait n times as long), but also an issue of transactionality (usually you want all to succeed or fail, not get an intermediate state) and atomicity (user leaves page mid-stream will execute only half the requests). Also, maybe if they don't give you the endpoint, they should at least fix that bug. Not serving an endpoint concurrently is outrageous. Your backend guys are wrong here, very wrong.
– Ingo Bürk
Nov 21 at 7:00