# "if" within a loop not sending messages in correct order

**URL:** <https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488>\
**Category:** General\
**Created:** [24 September 2021 19:59 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488 "2021-09-24T19:59:32Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![notnice](https://avatars.discourse-cdn.com/v4/letter/n/da6949/32.png) [@notnice](https://discourse.nodered.org/u/notnice)\
**Post date:** [24 September 2021 19:59 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488/1 "2021-09-24T19:59:32Z")

</div>

I have a loop that works, and within that i'm using "if" to check the difference in days between 2 dates. When the "if" is matched I'm setting some flow variables which are used by the next node to send emails with other flow variable data.

For testing the incoming array has 2 entries and their expiry dates match the 30 day difference. They are correctly matched by the "if" statement.

As below debug output, within the loop the email addresses at array index 0 and 1 are correctly pulled out and the loop counter increments from 0 to 1. However, it appears from the order of the debug output the node.send's don't execute until the loop has finished, and this results in the next node only using the 2nd email address thats stored in the flow variable at that time (same for the other flow variables).

The debug message order I would expect to see is:  
emailaddress-1 / loop count: 0 / debug 1 / emailaddress-1 then emailaddress-2 / loop count: 1 / debug 1 / emailaddress-2

I've tried using node.send in different places with no succcess. I also read up a bit on " Asynchronous context access" which might be related to my issue, but couldn't figure it. Bit confused about whether it should be synchronous or asynchronous processing and how to achieve the correct result.

Sure its a school boy error 🙄

24/09/2021, 20:21:08node: Check for expiring DPSK & send EMail notification  
function : (warn)  
"email: emailaddress-1"

24/09/2021, 20:21:08node: Check for expiring DPSK & send EMail notification  
function : (warn)  
"loop count: 0"

24/09/2021, 20:21:08node: Check for expiring DPSK & send EMail notification  
function : (warn)  
"email: emailaddress-2"

24/09/2021, 20:21:08node: Check for expiring DPSK & send EMail notification  
function : (warn)  
"loop count: 1"

24/09/2021, 20:21:08node: debug 1  
msg : Object  
{ \_msgid: "6483b845c5ad0ace" }

24/09/2021, 20:21:08node: debug 1  
msg : Object  
{ \_msgid: "6483b845c5ad0ace" }

24/09/2021, 20:21:08node: Check DPSK Action & Format Notifications  
function : (warn)  
"email: emailaddress-2"

24/09/2021, 20:21:08node: Check DPSK Action & Format Notifications  
function : (warn)  
"email: emailaddress-2"

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/2/326ba2ed4416d96e8a6ed0729ea20446ef6206da.png)

First node:

```auto
//create newMsg & initialise variables
var newMsg = {};
var datefromDPSKexpiry = "";
var microSecondsDiff = "";
var daysDiff = "";
var todaysDateTimeStamp = new Date(flow.get("todaysDate")).getTime();

//Set totalCount to number of Active DPSK received in the array
var totalCount = msg.payload.page.totalCount;

//Loop through the received DPSK array and check expiration = 14 days
//If it is then format and send EMail notification
for(counter = 0; counter < (totalCount); counter++) {
    flow.set("dpskExpiring", false);

    datefromDPSKexpiry = new Date(new Date(msg.payload.contents[counter].expirationDateTime)).getTime();
    microSecondsDiff = Math.abs(datefromDPSKexpiry - todaysDateTimeStamp);
    // Math.round is used instead of Math.floor to account for certain DST cases
    // Number of milliseconds per day = 24 hrs/day * 60 minutes/hour * 60 seconds/minute * 1000 ms/second
    daysDiff = Math.round(microSecondsDiff / (1000 * 60 * 60 * 24));

    //Check if the current DPSK being checked in the array DPSK will expire in 30 days
    //If it does then send EMail notification
    if (daysDiff === 30) {
        flow.set("dpskExpiring", true)
        flow.set("serviceLevel", msg.payload.contents[counter].name);
        flow.set("userEmail", msg.payload.contents[counter].thirdPartyId);
        flow.set("dpskPassphrase", msg.payload.contents[counter].passphrase);
        flow.set("dpskExpiry", msg.payload.contents[counter].expirationDateTime);
        
        node.warn("email: " +flow.get("userEmail"));
        node.warn("loop count: " +counter);
        
        node.send(newMsg);
        node.done();
    }
}
return;

```

Second Node:

```auto
//If DPSK is Expiring soon based on # of days left threshold then format EMail Notification & send
if (flow.get("dpskExpiring") === true) {
    
    node.warn("email: " +flow.get("userEmail"))
    
    newMsg.topic = "Your Wi-Fi Access Key (passphrase) is due to Expire";
    newMsg.payload = "<font size = 3>Your Wi-Fi Access Key <B>"+flow.get("dpskPassphrase")+"</B> for the Wi-Fi network <B>"+flow.get("wifiNetwork")+"</B> will expire in 2 weeks time.<BR><BR>The Access Key is valid until <B>"+flow.get("readableExpiryDate")+"</B><BR><BR>Your current Service is: <B>"+flow.get("serviceLevel")+"</B><BR><BR>Please renew your access key by clicking the link below<br><a href='http://10.10.10.10:1880/Login'>Login to Tenant Wi-Fi Access Portal</a>";
    return [null,newMsg]; 
}

```

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [24 September 2021 21:06 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488/2 "2021-09-24T21:06:16Z")

</div>

The node.send() calls execute immediately, but the messages will be queued at the front of the next node. The function will run till it finishes before the next node gets run. The solution is not to use context, but to put the data into the message and pass it on that way. So put the data into newMsg before sending it.  
Move the declaration of newMsg inside the loop though, and change it to  
`let newMsg = {}`  
then it will be a new message each time round the loop, otherwise you will be repeatedly changing the same newMsg and sending it. Because javascript objects are accessed by reference then the message effectively contains a pointer to newMsg and if you don't make a new one each time then all the messages will reference the same object and you will have the same problem.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [24 September 2021 21:06 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488/3 "2021-09-24T21:06:24Z")

</div>

Don't set context, just send an object with all the properties you need.

---

<div class="post-metadata">

**Author:** ![notnice](https://avatars.discourse-cdn.com/v4/letter/n/da6949/32.png) [@notnice](https://discourse.nodered.org/u/notnice)\
**Post date:** [25 September 2021 08:20 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488/4 "2021-09-25T08:20:40Z")

</div>

Thx Steve and Colin for the suggestions.  
I have changed the first node to this (just an extract of the part changed, excludes the loop):

```auto
    if (daysDiff === 29) {
        let newMsg = {};        
        newMsg.payload = {
        "dpskExpiring": true,
        "serviceLevel": msg.payload.contents[counter].name,
        "userEmail": msg.payload.contents[counter].thirdPartyId,
        "dpskPassphrase": msg.payload.contents[counter].passphrase,
        "dpskExpiry": msg.payload.contents[counter].expirationDateTime
        }
        node.send(newMsg);
        node.done();        
    }

```

I have updated the next node as below, using flow.set for email address as the next node on uses that to set the email To: field.

```auto
if (msg.payload.dpskExpiring === true) {
    flow.set("userEmail", msg.payload.userEmail);
    node.warn("email is: "+flow.get("userEmail"));
    newMsg.topic = "Your Wi-Fi Access Key (passphrase) is due to Expire";
    newMsg.payload = "<font size = 3>Your Wi-Fi Access Key <B>"+msg.payload.dpskPassphrase+"</B> for the Wi-Fi network <B>"+flow.get("wifiNetwork")+"</B> will expire in 2 weeks time.<BR><BR>The Access Key is valid until <B>"+flow.get("readableExpiryDate")+"</B><BR><BR>Your current Service is: <B>"+msg.payload.serviceLevel+"</B><BR><BR>Please renew your access key by clicking the link below<br><a href='http://194.60.94.30:1880/Login'>Login to Tenant Wi-Fi Access Portal</a>";
    return [null,newMsg]; 
    }
return;

```

This is the formatting of the email before its passed to the send email node. I'm using flow.get for userEmail as other parts of my workflow also feed into this node for email notifications and the email address gets set correctly.

```auto
newMsg = {};
newMsg.to = flow.get("userEmail");
newMsg.from = Settings.EMAIL.EMAILfrom;
newMsg.topic = msg.topic;
newMsg.payload = msg.payload;
return newMsg;

```

When I now test the result is as below in debug. An improvement, but the actual emails still both get sent to the 2nd email address in the original array. The other parameters passphrase and service are correct (unique) for each user in the email.

25/09/2021, 08:59:42node: Check DPSK Action & Format Notifications  
function : (warn)  
"email is: emailaddress-1"

25/09/2021, 08:59:42node: debug 1  
msg : Object  
object  
payload: object  
dpskExpiring: true  
serviceLevel: "AFFORDABLE-SILVER"  
userEmail: "emailaddress-1"  
dpskPassphrase: "9rf2UHcP1LqP"  
dpskExpiry: "2021-10-24T10:33:49Z"  
\_msgid: "62ca95e3484a2ebd"  
settings: object

25/09/2021, 08:59:42node: Check DPSK Action & Format Notifications  
function : (warn)  
"email is: emailaddress-2"

25/09/2021, 08:59:42node: debug 1  
msg : Object  
object  
payload: object  
dpskExpiring: true  
serviceLevel: "PRIVATE-SILVER"  
userEmail: "emailaddress-2"  
dpskPassphrase: "daLb6MEKUmD7"  
dpskExpiry: "2021-10-24T10:37:43Z"  
\_msgid: "62ca95e3484a2ebd"  
settings: object

This a debug output connected to the node that submits the data to be sent by email send node. You can see its the same To: email adress in both, the first should be emailaddress-1. The passphrase and service parameters are however correctly unique.

25/09/2021, 09:10:38node: debug 2  
Your Wi-Fi Access Key (passphrase) is due to Expire : msg : Object  
object  
to: " **emailaddress-2**"  
from: "[alert@comm.com](mailto:alert@comm.com)"  
topic: "Your Wi-Fi Access Key (passphrase) is due to Expire"  
payload: "Your Wi-Fi Access Key **9rf2UHcP1LqP** for the Wi-Fi network **Tenant Wi-Fi** will expire in 2 weeks time.  
  
The Access Key is valid until **Sunday, October 24th 2021 at 00:01**  
  
Your current Service is: **AFFORDABLE-SILVER**  
  
Please renew your access key by clicking the link below  
[Login to Tenant Wi-Fi Access Portal](http://194.60.94.30:1880/Login)"  
\_msgid: "4562596db27ac25d"

25/09/2021, 09:10:38node: debug 2  
Your Wi-Fi Access Key (passphrase) is due to Expire : msg : Object  
object  
to: " **emailaddress-2**"  
from: "[alert@comm.com](mailto:alert@comm.com)"  
topic: "Your Wi-Fi Access Key (passphrase) is due to Expire"  
payload: "Your Wi-Fi Access Key **daLb6MEKUmD7** for the Wi-Fi network **Tenant Wi-Fi** will expire in 2 weeks time.  
  
The Access Key is valid until **Sunday, October 24th 2021 at 00:01**  
  
Your current Service is: **PRIVATE-SILVER**  
  
Please renew your access key by clicking the link below  
[Login to Tenant Wi-Fi Access Portal](http://194.60.94.30:1880/Login)"  
\_msgid: "4562596db27ac25d"

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [25 September 2021 08:50 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488/5 "2021-09-25T08:50:55Z")

</div>

Isn't it exactly the same problem? The setting in flow context "userEmail" is getting overwritten before it is sent to the email node. Don't use context, pass it to the email node in the message.

---

<div class="post-metadata">

**Author:** ![notnice](https://avatars.discourse-cdn.com/v4/letter/n/da6949/32.png) [@notnice](https://discourse.nodered.org/u/notnice)\
**Post date:** [25 September 2021 09:47 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488/6 "2021-09-25T09:47:57Z")

</div>

Yeah, just further down the flow ☹

The reason I am setting it is as a flow variable is because there are other workflow branches that also feed into the same email formatting node before sending, and they all works fine. Can't understand why it gets over-written in this case when it looks correct up to that point.

I'll update it so not using flow variable for this part of the workflow.

Thx again for the pateint feedback.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [25 September 2021 09:55 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488/7 "2021-09-25T09:55:58Z")

</div>

> [@notnice](#):
>
> Can't understand why it gets over-written in this case when it looks correct up to that point.

As before, because you are sending two messages in quick succession (unless I misunderstand what you are doing) so the second one overwrites the flow variable before the email formatting node gets to handle the first one.

Change them all to pass it in the message. It really is safer to not use context in this situation (in fact I never use it for such things). Pass it in the message. I don't know the rest of your flows, but if you have multiple places where you setup the userEmail context var then are you absolutely certain that there is no possibility that two of those places could get messages very close together? It may work for a year without a problem and then by coincidence that happens and then you will send a email to the wrong address.

---

<div class="post-metadata">

**Author:** ![notnice](https://avatars.discourse-cdn.com/v4/letter/n/da6949/32.png) [@notnice](https://discourse.nodered.org/u/notnice)\
**Post date:** [25 September 2021 09:58 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488/8 "2021-09-25T09:58:48Z")

</div>

Ok, changed that part of the workflow to pass the email as newMsg.userEmail and all works now. Thx for the pointers.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [25 September 2021 10:19 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488/9 "2021-09-25T10:19:00Z")

</div>

By the way, you generally don't need to (and in fact shouldn't) make a new message in a function unless you are sending multiple messages using node.send(). It is often useful to be able to pass message properties through a node unaffected, and those will get lost if you make a new message. Instead, modify the msg passed in and send that on.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [9 October 2021 10:19 UTC](https://discourse.nodered.org/t/if-within-a-loop-not-sending-messages-in-correct-order/51488/10 "2021-10-09T10:19:48Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
