sane way to pass/keep a value throwout a long pipe









up vote
3
down vote

favorite












Assuming i have the following rxjs pipe:



start$.pip(
map((id)=> ), //I want to save the "id" value to be used in the end of the pipe
map(...),
switchMap(...),
map(...),
switchMap(...),
map(...),
switchMap(...),
switchMap(...)//I need the original "id" value here
).subscribe()


Is there a way to keep the 'id" value throughout the pip so it can be used at the end of the pipe?



Motivation: It comes often in NGRX effects where i want to use the original payload data of the triggering source action for generating the new action.










share|improve this question























  • I think you have to pass the id from one operator to the next one throught the whole chain. You can try something like that map(id => (id: id, data:data))
    – René Winkler
    Jul 29 at 7:11










  • It's hard to say without any context, but I suggest to start with switchMap and create a nested pipe inside.
    – a better oliver
    Jul 29 at 17:06














up vote
3
down vote

favorite












Assuming i have the following rxjs pipe:



start$.pip(
map((id)=> ), //I want to save the "id" value to be used in the end of the pipe
map(...),
switchMap(...),
map(...),
switchMap(...),
map(...),
switchMap(...),
switchMap(...)//I need the original "id" value here
).subscribe()


Is there a way to keep the 'id" value throughout the pip so it can be used at the end of the pipe?



Motivation: It comes often in NGRX effects where i want to use the original payload data of the triggering source action for generating the new action.










share|improve this question























  • I think you have to pass the id from one operator to the next one throught the whole chain. You can try something like that map(id => (id: id, data:data))
    – René Winkler
    Jul 29 at 7:11










  • It's hard to say without any context, but I suggest to start with switchMap and create a nested pipe inside.
    – a better oliver
    Jul 29 at 17:06












up vote
3
down vote

favorite









up vote
3
down vote

favorite











Assuming i have the following rxjs pipe:



start$.pip(
map((id)=> ), //I want to save the "id" value to be used in the end of the pipe
map(...),
switchMap(...),
map(...),
switchMap(...),
map(...),
switchMap(...),
switchMap(...)//I need the original "id" value here
).subscribe()


Is there a way to keep the 'id" value throughout the pip so it can be used at the end of the pipe?



Motivation: It comes often in NGRX effects where i want to use the original payload data of the triggering source action for generating the new action.










share|improve this question















Assuming i have the following rxjs pipe:



start$.pip(
map((id)=> ), //I want to save the "id" value to be used in the end of the pipe
map(...),
switchMap(...),
map(...),
switchMap(...),
map(...),
switchMap(...),
switchMap(...)//I need the original "id" value here
).subscribe()


Is there a way to keep the 'id" value throughout the pip so it can be used at the end of the pipe?



Motivation: It comes often in NGRX effects where i want to use the original payload data of the triggering source action for generating the new action.







rxjs ngrx






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jul 29 at 7:06

























asked Jul 29 at 6:59









amit

6741129




6741129











  • I think you have to pass the id from one operator to the next one throught the whole chain. You can try something like that map(id => (id: id, data:data))
    – René Winkler
    Jul 29 at 7:11










  • It's hard to say without any context, but I suggest to start with switchMap and create a nested pipe inside.
    – a better oliver
    Jul 29 at 17:06
















  • I think you have to pass the id from one operator to the next one throught the whole chain. You can try something like that map(id => (id: id, data:data))
    – René Winkler
    Jul 29 at 7:11










  • It's hard to say without any context, but I suggest to start with switchMap and create a nested pipe inside.
    – a better oliver
    Jul 29 at 17:06















I think you have to pass the id from one operator to the next one throught the whole chain. You can try something like that map(id => (id: id, data:data))
– René Winkler
Jul 29 at 7:11




I think you have to pass the id from one operator to the next one throught the whole chain. You can try something like that map(id => (id: id, data:data))
– René Winkler
Jul 29 at 7:11












It's hard to say without any context, but I suggest to start with switchMap and create a nested pipe inside.
– a better oliver
Jul 29 at 17:06




It's hard to say without any context, but I suggest to start with switchMap and create a nested pipe inside.
– a better oliver
Jul 29 at 17:06












3 Answers
3






active

oldest

votes

















up vote
4
down vote



accepted










I think the correct way is to make another closure



const processId = (id) => observableOf(id)
.pipe(
map(() => ... ),
map(...),
switchMap(...),
map(...),
switchMap(...),
map(...),
switchMap(...),
switchMap(...) // Use id here
);

const getPipe = () => start$
.pipe(switchMap(processId));


Storing local variable as a side effect in getPipe is OK, but it can break if start$ Observable emits more values.






share|improve this answer




















  • totally correct - that's the way to do it
    – Picci
    Jul 29 at 19:11

















up vote
2
down vote













The way suggested by @René Winkler is the right way for short pipes.



If the pipe is long though it can be tedious and somehow can make the code less readable.



One alternative approach can be to create a function (or method) where you define id as a local variable that you set within the first map so that you can use it at your convenience all along the chain of operators, something like



getLongPipe(id) 
let _id;
return start$.pipe(
map((id)=> _id = id; ....), //I want to save the "id" value to be used in the end of the pipe
map(...),
switchMap(...),
map(...),
switchMap(...),
map(...),
switchMap(...),
switchMap(...)//Here you can use _id
)


getLongPipe(id).subscribe()





share|improve this answer






















  • but "id" is an event item of "start$"...
    – amit
    Jul 29 at 7:31










  • You are right. I wrote about input variable while what I had in mind was local variable. See the updated answer.
    – Picci
    Jul 29 at 8:13

















up vote
1
down vote













The closure seems correct, would like to add a detail gotcha, I boiled down to a base case:



Say you want to get to the end of a stream, and based on something that happened earlier, do this or that. So you use the closure pattern, start with a flag of false, and later in the pipe, set it to true. At the end of the pipe, do this or that depending on the flag. Works nicely.



Problem is, after the first time, if that value got set to true, depending on your use (say, an NGRX effect, which is where I ran into this) it'll be true forever (no surprise, the closure persists) unless something else sets it back to the default (false).



Basic form/fix:



stream$ = ( ( my_flag = false ) => 
return ( otherStream$
.variousOperators ( ... )
.do ( x =>
my_flag = some_condition_of_x ? true : false
)
.map ( x => my_flag ? a : b )
.do ( x =>
my_flag = false; // reset
)
.map ( x => x )
);
) ();


Had a pretty tricky case involving some NGRX effects that was greatly (greatly) simplified by this.






share|improve this answer




















    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',
    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
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51578014%2fsane-way-to-pass-keep-a-value-throwout-a-long-pipe%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    4
    down vote



    accepted










    I think the correct way is to make another closure



    const processId = (id) => observableOf(id)
    .pipe(
    map(() => ... ),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    switchMap(...) // Use id here
    );

    const getPipe = () => start$
    .pipe(switchMap(processId));


    Storing local variable as a side effect in getPipe is OK, but it can break if start$ Observable emits more values.






    share|improve this answer




















    • totally correct - that's the way to do it
      – Picci
      Jul 29 at 19:11














    up vote
    4
    down vote



    accepted










    I think the correct way is to make another closure



    const processId = (id) => observableOf(id)
    .pipe(
    map(() => ... ),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    switchMap(...) // Use id here
    );

    const getPipe = () => start$
    .pipe(switchMap(processId));


    Storing local variable as a side effect in getPipe is OK, but it can break if start$ Observable emits more values.






    share|improve this answer




















    • totally correct - that's the way to do it
      – Picci
      Jul 29 at 19:11












    up vote
    4
    down vote



    accepted







    up vote
    4
    down vote



    accepted






    I think the correct way is to make another closure



    const processId = (id) => observableOf(id)
    .pipe(
    map(() => ... ),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    switchMap(...) // Use id here
    );

    const getPipe = () => start$
    .pipe(switchMap(processId));


    Storing local variable as a side effect in getPipe is OK, but it can break if start$ Observable emits more values.






    share|improve this answer












    I think the correct way is to make another closure



    const processId = (id) => observableOf(id)
    .pipe(
    map(() => ... ),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    switchMap(...) // Use id here
    );

    const getPipe = () => start$
    .pipe(switchMap(processId));


    Storing local variable as a side effect in getPipe is OK, but it can break if start$ Observable emits more values.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jul 29 at 10:47









    m1ch4ls

    1,586721




    1,586721











    • totally correct - that's the way to do it
      – Picci
      Jul 29 at 19:11
















    • totally correct - that's the way to do it
      – Picci
      Jul 29 at 19:11















    totally correct - that's the way to do it
    – Picci
    Jul 29 at 19:11




    totally correct - that's the way to do it
    – Picci
    Jul 29 at 19:11












    up vote
    2
    down vote













    The way suggested by @René Winkler is the right way for short pipes.



    If the pipe is long though it can be tedious and somehow can make the code less readable.



    One alternative approach can be to create a function (or method) where you define id as a local variable that you set within the first map so that you can use it at your convenience all along the chain of operators, something like



    getLongPipe(id) 
    let _id;
    return start$.pipe(
    map((id)=> _id = id; ....), //I want to save the "id" value to be used in the end of the pipe
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    switchMap(...)//Here you can use _id
    )


    getLongPipe(id).subscribe()





    share|improve this answer






















    • but "id" is an event item of "start$"...
      – amit
      Jul 29 at 7:31










    • You are right. I wrote about input variable while what I had in mind was local variable. See the updated answer.
      – Picci
      Jul 29 at 8:13














    up vote
    2
    down vote













    The way suggested by @René Winkler is the right way for short pipes.



    If the pipe is long though it can be tedious and somehow can make the code less readable.



    One alternative approach can be to create a function (or method) where you define id as a local variable that you set within the first map so that you can use it at your convenience all along the chain of operators, something like



    getLongPipe(id) 
    let _id;
    return start$.pipe(
    map((id)=> _id = id; ....), //I want to save the "id" value to be used in the end of the pipe
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    switchMap(...)//Here you can use _id
    )


    getLongPipe(id).subscribe()





    share|improve this answer






















    • but "id" is an event item of "start$"...
      – amit
      Jul 29 at 7:31










    • You are right. I wrote about input variable while what I had in mind was local variable. See the updated answer.
      – Picci
      Jul 29 at 8:13












    up vote
    2
    down vote










    up vote
    2
    down vote









    The way suggested by @René Winkler is the right way for short pipes.



    If the pipe is long though it can be tedious and somehow can make the code less readable.



    One alternative approach can be to create a function (or method) where you define id as a local variable that you set within the first map so that you can use it at your convenience all along the chain of operators, something like



    getLongPipe(id) 
    let _id;
    return start$.pipe(
    map((id)=> _id = id; ....), //I want to save the "id" value to be used in the end of the pipe
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    switchMap(...)//Here you can use _id
    )


    getLongPipe(id).subscribe()





    share|improve this answer














    The way suggested by @René Winkler is the right way for short pipes.



    If the pipe is long though it can be tedious and somehow can make the code less readable.



    One alternative approach can be to create a function (or method) where you define id as a local variable that you set within the first map so that you can use it at your convenience all along the chain of operators, something like



    getLongPipe(id) 
    let _id;
    return start$.pipe(
    map((id)=> _id = id; ....), //I want to save the "id" value to be used in the end of the pipe
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    map(...),
    switchMap(...),
    switchMap(...)//Here you can use _id
    )


    getLongPipe(id).subscribe()






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jul 29 at 8:12

























    answered Jul 29 at 7:20









    Picci

    5,05252248




    5,05252248











    • but "id" is an event item of "start$"...
      – amit
      Jul 29 at 7:31










    • You are right. I wrote about input variable while what I had in mind was local variable. See the updated answer.
      – Picci
      Jul 29 at 8:13
















    • but "id" is an event item of "start$"...
      – amit
      Jul 29 at 7:31










    • You are right. I wrote about input variable while what I had in mind was local variable. See the updated answer.
      – Picci
      Jul 29 at 8:13















    but "id" is an event item of "start$"...
    – amit
    Jul 29 at 7:31




    but "id" is an event item of "start$"...
    – amit
    Jul 29 at 7:31












    You are right. I wrote about input variable while what I had in mind was local variable. See the updated answer.
    – Picci
    Jul 29 at 8:13




    You are right. I wrote about input variable while what I had in mind was local variable. See the updated answer.
    – Picci
    Jul 29 at 8:13










    up vote
    1
    down vote













    The closure seems correct, would like to add a detail gotcha, I boiled down to a base case:



    Say you want to get to the end of a stream, and based on something that happened earlier, do this or that. So you use the closure pattern, start with a flag of false, and later in the pipe, set it to true. At the end of the pipe, do this or that depending on the flag. Works nicely.



    Problem is, after the first time, if that value got set to true, depending on your use (say, an NGRX effect, which is where I ran into this) it'll be true forever (no surprise, the closure persists) unless something else sets it back to the default (false).



    Basic form/fix:



    stream$ = ( ( my_flag = false ) => 
    return ( otherStream$
    .variousOperators ( ... )
    .do ( x =>
    my_flag = some_condition_of_x ? true : false
    )
    .map ( x => my_flag ? a : b )
    .do ( x =>
    my_flag = false; // reset
    )
    .map ( x => x )
    );
    ) ();


    Had a pretty tricky case involving some NGRX effects that was greatly (greatly) simplified by this.






    share|improve this answer
























      up vote
      1
      down vote













      The closure seems correct, would like to add a detail gotcha, I boiled down to a base case:



      Say you want to get to the end of a stream, and based on something that happened earlier, do this or that. So you use the closure pattern, start with a flag of false, and later in the pipe, set it to true. At the end of the pipe, do this or that depending on the flag. Works nicely.



      Problem is, after the first time, if that value got set to true, depending on your use (say, an NGRX effect, which is where I ran into this) it'll be true forever (no surprise, the closure persists) unless something else sets it back to the default (false).



      Basic form/fix:



      stream$ = ( ( my_flag = false ) => 
      return ( otherStream$
      .variousOperators ( ... )
      .do ( x =>
      my_flag = some_condition_of_x ? true : false
      )
      .map ( x => my_flag ? a : b )
      .do ( x =>
      my_flag = false; // reset
      )
      .map ( x => x )
      );
      ) ();


      Had a pretty tricky case involving some NGRX effects that was greatly (greatly) simplified by this.






      share|improve this answer






















        up vote
        1
        down vote










        up vote
        1
        down vote









        The closure seems correct, would like to add a detail gotcha, I boiled down to a base case:



        Say you want to get to the end of a stream, and based on something that happened earlier, do this or that. So you use the closure pattern, start with a flag of false, and later in the pipe, set it to true. At the end of the pipe, do this or that depending on the flag. Works nicely.



        Problem is, after the first time, if that value got set to true, depending on your use (say, an NGRX effect, which is where I ran into this) it'll be true forever (no surprise, the closure persists) unless something else sets it back to the default (false).



        Basic form/fix:



        stream$ = ( ( my_flag = false ) => 
        return ( otherStream$
        .variousOperators ( ... )
        .do ( x =>
        my_flag = some_condition_of_x ? true : false
        )
        .map ( x => my_flag ? a : b )
        .do ( x =>
        my_flag = false; // reset
        )
        .map ( x => x )
        );
        ) ();


        Had a pretty tricky case involving some NGRX effects that was greatly (greatly) simplified by this.






        share|improve this answer












        The closure seems correct, would like to add a detail gotcha, I boiled down to a base case:



        Say you want to get to the end of a stream, and based on something that happened earlier, do this or that. So you use the closure pattern, start with a flag of false, and later in the pipe, set it to true. At the end of the pipe, do this or that depending on the flag. Works nicely.



        Problem is, after the first time, if that value got set to true, depending on your use (say, an NGRX effect, which is where I ran into this) it'll be true forever (no surprise, the closure persists) unless something else sets it back to the default (false).



        Basic form/fix:



        stream$ = ( ( my_flag = false ) => 
        return ( otherStream$
        .variousOperators ( ... )
        .do ( x =>
        my_flag = some_condition_of_x ? true : false
        )
        .map ( x => my_flag ? a : b )
        .do ( x =>
        my_flag = false; // reset
        )
        .map ( x => x )
        );
        ) ();


        Had a pretty tricky case involving some NGRX effects that was greatly (greatly) simplified by this.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 8 at 19:07









        Tim Consolazio

        2,0201613




        2,0201613



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51578014%2fsane-way-to-pass-keep-a-value-throwout-a-long-pipe%23new-answer', 'question_page');

            );

            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







            Popular posts from this blog

            𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

            Edmonton

            Crossroads (UK TV series)