# Sending messages inside callback functions

**URL:** <https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683>\
**Category:** Developing Nodes\
**Created:** [2 December 2019 08:48 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683 "2019-12-02T08:48:08Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [2 December 2019 08:48 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/1 "2019-12-02T08:48:09Z")

</div>

I have been working on a custom node for what seems like an eternity (worse it is yet another scheduling node 🤪. I have it close to where I want it but have come across one interesting problem.

The node uses a callback function to fire time based events. Inside the callback function I don't do anything special, just send on the message with _node.send(msg)_. However in the most basic test configuration (scheduling one event after another), only the LAST firing of the callback sends the msg.

I know the previous fired events contain the msg because it is output to the console correctly at the correct time.

I am hoping I have left something simple out like node cleanup etc, but any clues as to where to start looking would be appreciated.

Thanks  
Bob

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [2 December 2019 12:26 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/3 "2019-12-02T12:26:41Z")

</div>

> [@Bobo](#):
>
> only the LAST firing of the callback sends the ms

Hey Bob,  
that should work what you are doing. Perhaps you should share a code snippet ...  
[Here](https://github.com/bartbutenaers/node-red-contrib-msg-resend/blob/master/msg_resend.js#L226) you can see that I do something similar in my **node-red-contrib-msg-resend** node. For example:

```auto
var yourTimerId = setInterval(function() {
   node.send( {payload: "test"});
}, 5000);

```

Make sure that you create a **NEW** message every time the callback is triggered! Because when you resend the same message over and over again, you will get weird results (as soon as the next nodes in the flow start changing the content of that single message over and over again)...

And don't forget to stop your timer, as soon as your node is cleaned up:

```auto
node.on("close", function() {
    clearInterval(yourTimerId );
}

```

Otherwise you will end up with multiple timers running in parallel ...  
Bart

---

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [3 December 2019 05:28 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/4 "2019-12-03T05:28:42Z")

</div>

Thanks for the tips Bart. Unfortunately I'm still at a loss to understand where I have made the mistake, or perhaps I am misunderstanding something fundamental regarding sending messages.

A code snippet probably won't help you much but it will clearly demonstrate the issue:

```auto
                    var j = schedule.scheduleJob(jb, date, function () {

                        var id_status = context.get('cancel-date');

                        console.log('single date - ', jb);
                        console.log('message = ', msg);
                        send(msg);
                    });

```

The above is a call made to the node-schedule node - [https://github.com/node-schedule/node-schedule](https://github.com/node-schedule/node-schedule).

What I don't understand is the output from the console is always correct. There is a msg displaying the correct msg\_id and info when the event is fired. There is just **no output at the debug node** from send(msg).

---

<div class="post-metadata">

**Author:** ![kuema](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kuema/32/6542_2.png) [@kuema](https://discourse.nodered.org/u/kuema)\
**Post date:** [3 December 2019 06:39 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/5 "2019-12-03T06:39:58Z")

</div>

Maybe a silly question, but you just call `send(msg);`. Where/how is `send` defined in your code?

The send function is available on the enclosing function that defines your node. So unless you do something like `let send = this.send;` beforehand, that code will not work, because `send` is not in the closure of your callback function.

Thinking even further, just calling `send()` may mess up the send function itself, because `this` will not be bound to the node function. You'd have to do something like

```auto
let node = this;

var j = schedule.scheduleJob(jb, date, function () {

                        var id_status = context.get('cancel-date');

                        console.log('single date - ', jb);
                        console.log('message = ', msg);
                        node.send(msg);
                    });

```

---

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [3 December 2019 06:47 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/6 "2019-12-03T06:47:33Z")

</div>

No silly questions, except perhaps mine.

I "upgraded" the node to be compliant with NR 1.x via [https://nodered.org/docs/creating-nodes/node-js#sending-messages](https://nodered.org/docs/creating-nodes/node-js#sending-messages).

Prior to that I was using _node.send(msg)_ with same results.

---

<div class="post-metadata">

**Author:** ![kuema](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kuema/32/6542_2.png) [@kuema](https://discourse.nodered.org/u/kuema)\
**Post date:** [3 December 2019 06:50 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/7 "2019-12-03T06:50:32Z")

</div>

Yes, but the new Send API only applies to nodes with an input using the `on('input')` event.

In your case you are generating the messages yourself I suspect, so you would have to use `node.send()` anyway.

I would need to see more of your node's code to find the problem. Is it shared on Github?

---

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [3 December 2019 07:01 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/8 "2019-12-03T07:01:18Z")

</div>

Not as yet no. But if you are willing to take a look I will gladly get that done.

I am out of ideas and js knowledge 😬

---

<div class="post-metadata">

**Author:** ![kuema](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kuema/32/6542_2.png) [@kuema](https://discourse.nodered.org/u/kuema)\
**Post date:** [3 December 2019 07:10 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/9 "2019-12-03T07:10:38Z")

</div>

Working from your example, your code _should_ look something like the following. Unless I completely misunderstand what your node is supposed to do. 🤓

```auto
function MyNode(config) {
    RED.nodes.createNode(this, config);

    const node = this;

    var j = schedule.scheduleJob(jb, date, function () {

        var id_status = context.get('cancel-date');

        let msg = {payload: 'foo'};

        console.log('single date - ', jb);
        console.log('message = ', msg);
        node.send(msg);
    });
}

```

Another question... where do you get the message object from? Or are you trying to schedule from within a `on('input')` event??? That would be a completely different case.

---

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [3 December 2019 07:28 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/10 "2019-12-03T07:28:19Z")

</div>

> [@kuema](#):
>
> Another question..

Ok, so it is a fairly basic daily scheduler node using the node-schedule node. I am aware that that particular nodejs node does have a few bugs but se la vì.

Either the schedule can be passed in, or created in the node's editor. I then add msg.alarm\_date.xxx which forms the scheduled date for the callback function to fire.

Shall I just post the code here?

---

<div class="post-metadata">

**Author:** ![kuema](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kuema/32/6542_2.png) [@kuema](https://discourse.nodered.org/u/kuema)\
**Post date:** [3 December 2019 07:30 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/11 "2019-12-03T07:30:08Z")

</div>

Yes, that would be the easiest way. I have a suspicion what might be the problem, but I would need to see the code for that. 🤓

---

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [3 December 2019 07:32 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/12 "2019-12-03T07:32:06Z")

</div>

Remember this is primarily a self-learning exercise, as well as providing something which I would find useful, should it ever work properly 😁

---

<div class="post-metadata">

**Author:** ![kuema](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kuema/32/6542_2.png) [@kuema](https://discourse.nodered.org/u/kuema)\
**Post date:** [3 December 2019 07:46 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/13 "2019-12-03T07:46:13Z")

</div>

Debugging code of other people is part of the learning exercise. As most people with a computer science background, we love to solve problems. 😁

---

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [3 December 2019 07:46 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/14 "2019-12-03T07:46:36Z")

</div>

```auto
var schedule = require('node-schedule');

module.exports = function (RED) {
    "use strict";
    function DailySchedulerNode(config) {
        RED.nodes.createNode(this, config);
        var node = this;
        var context = this.context().flow;

        this.on('input', function (msg) {

            this.hour = config.hour;
            this.month = config.month;
            this.day = config.day;
            this.minute = config.minute;
            this.recur = config.recur;
            this.year = config.year;
            this.desc = config.desc;
            this.early = config.early;
            this.idx = config.idx;

            var editor, inputmsg = false;

            if (msg.hasOwnProperty("alarm_date") && msg.alarm_date.hasOwnProperty("hours") && msg.alarm_date.hasOwnProperty("years") &&
                msg.alarm_date.hasOwnProperty("months") && msg.alarm_date.hasOwnProperty("date") && msg.alarm_date.hasOwnProperty("desc")) {

                // ***************************************************
                // INPUT FROM MSG.ALARM_DATE

                this.status({ fill: "green", shape: "dot", text: "ok" });

                inputmsg = true;

                console.log('INCOMING MSG');

            } else if (node.month != '' && node.hour != '' && node.minute != '' && node.day != '' && node.desc != '') {

                // ***************************************************
                // INPUT FROM EDITOR

                console.log('The EDITOR worked.');

                this.status({ fill: "green", shape: "dot", text: "ok" });

                editor = true;

                msg.alarm_date = {};

                msg.alarm_date.years = Number(node.year);
                msg.alarm_date.months = Number(node.month);
                msg.alarm_date.date = Number(node.day);
                msg.alarm_date.hours = Number(node.hour);
                msg.alarm_date.minutes = Number(node.minute);
                msg.alarm_date.early = Number(node.early);
                msg.alarm_date.idx = node.idx;
                msg.alarm_date.desc = node.desc;
                msg.alarm_date.recur = node.recur;

            } else {
                msg.error = 'Date configuration error in Daily Scheduler node';
                console.log('Date configuration error in Daily Scheduler node');

                this.status({ fill: "red", shape: "dot", text: "config error" });
            }

            if (editor || inputmsg) {

                var jobname;

                if (msg.hasOwnProperty("alarm_date") && msg.alarm_date.hasOwnProperty("idx") && msg.alarm_date.idx != '') {
                    jobname = msg.alarm_date.idx;
                } else { jobname = msg._msgid; msg.alarm_date.idx = jobname; }

                if (msg.hasOwnProperty("alarm_date") && msg.alarm_date.hasOwnProperty("hours") && msg.alarm_date.hours != '') { }
                else { msg.alarm_date.hours = 0; }

                let jb = String(jobname);

                console.log(jb);

                if (msg.alarm_date.early > 0 || msg.alarm_date.recur) { // process for early reminders OR monthly recurring

                    var rule = new schedule.RecurrenceRule();
                    var earlyrem = msg.alarm_date.early + 1;

                    // change from minutes to dates *****************************....
                    var currentdate = new Date(msg.alarm_date.years, msg.alarm_date.months,
                        msg.alarm_date.date, msg.alarm_date.hours,
                        msg.alarm_date.minutes, 0, 0);

                    var earlydate = new Date(msg.alarm_date.years, msg.alarm_date.months,
                        msg.alarm_date.date, msg.alarm_date.hours,
                        msg.alarm_date.minutes - msg.alarm_date.early - 1, 0, 0);

                    if (msg.alarm_date.recur) { rule.month = [0, new schedule.Range(0, 11)]; } // monthly recurring

                    rule.date = msg.alarm_date.date;

                    rule.hour = msg.alarm_date.hours;

                    var j = schedule.scheduleJob(jb, { start: earlydate, end: currentdate, rule }, function () {

                        var id_status = context.get('cancel-date');

                        if (id_status == jb) {
                            schedule.scheduledJobs[jb].cancel();
                            console.log('CANCELLED ... early or recurring - ', jb);
                        } else {
                            earlyrem = earlyrem - 1;
                            console.log('early or recurring - ', jb);
                            console.log('Left - ', earlyrem);
                            msg.alarm_date.earlyrem = earlyrem;
                            node.send(msg);
                        }
                    });

                } else { // change to standard single date event

                    console.log('SINGLE DATE TRIGGER .....');

                    var date = new Date(msg.alarm_date.years, msg.alarm_date.months, msg.alarm_date.date,
                        msg.alarm_date.hours, msg.alarm_date.minutes, 0);

                    var j = schedule.scheduleJob(jb, date, function () {

                        / **************** MISSING MESSAGES */
                        var id_status = context.get('cancel-date');

                        console.log('single date - ', jb);
                        console.log('message = ', msg);
                        node.send(msg);

                    });

                }

            }

            node.send(msg);

        });

    }

    RED.nodes.registerType("daily-scheduler", DailySchedulerNode);
}

```

---

<div class="post-metadata">

**Author:** ![kuema](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kuema/32/6542_2.png) [@kuema](https://discourse.nodered.org/u/kuema)\
**Post date:** [3 December 2019 08:01 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/15 "2019-12-03T08:01:25Z")

</div>

Okay... so it isn't the thing I suspected regarding the binding of `this`.

But I see that you send the **same** message instantly and reuse it in your callbacks. By resending the same message reference you are in for trouble. It _may_ work in simple cases, but since your are setting lots of message properties and rely on them for your scheduling, you should clone the message using `RED.util.cloneMessage(msg);`. Otherwise the message will be modified by subsequent nodes in the meantime until your callback gets fired.

I would create the clone early in your `on('input')` function and use that clone in the scheduler callback.  
The original message can then be sent instantly (the last `node.send(msg);` in your code)

---

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [3 December 2019 08:04 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/16 "2019-12-03T08:04:47Z")

</div>

I did actually try cloning but did it in the callback. I shall try early as you suggest. Thanks.

---

<div class="post-metadata">

**Author:** ![kuema](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kuema/32/6542_2.png) [@kuema](https://discourse.nodered.org/u/kuema)\
**Post date:** [3 December 2019 08:10 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/17 "2019-12-03T08:10:07Z")

</div>

If you clone it within the callback, the original message is likely to be modified already.

So the general order should be

1. clone original
2. register/create callbacks, use cloned message within
3. send original message

---

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [3 December 2019 09:35 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/18 "2019-12-03T09:35:14Z")

</div>

No luck with cloning unfortunately.

So the test scenario is (using the nodes editor), set a schedule and deploy. Set another schedule and deploy. The first schedule msg gets sent to debug, the second (third etc) does not.

If you are still interested in solving the mystery I will stick my node up on github.

Cheers

---

<div class="post-metadata">

**Author:** ![kuema](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kuema/32/6542_2.png) [@kuema](https://discourse.nodered.org/u/kuema)\
**Post date:** [3 December 2019 09:40 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/19 "2019-12-03T09:40:55Z")

</div>

By debug you mean a debug node connected to your node?

One other thing, do you get the `console.log()` output from your scheduler callbacks? I'm curious if the callback gets fired at all 🤔

---

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [3 December 2019 10:01 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/20 "2019-12-03T10:01:57Z")

</div>

> [@kuema](#):
>
> do you get the `console.log()` output from your scheduler callbacks?

Yes indeed. My first thought was that the events were just not being fired, but the console logs show they are, with the correct msg id and data.

And yes, with a debug node at the end of my node.

---

<div class="post-metadata">

**Author:** ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)\
**Post date:** [3 December 2019 10:33 UTC](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683/21 "2019-12-03T10:33:23Z")

</div>

Another piece to the puzzle. The order in which the events are deployed (as per my testing scenario) affects which msg gets sent to debug (ie **last** deployed event will trigger debug only).

[Next page](https://discourse.nodered.org/t/sending-messages-inside-callback-functions/18683.md?page=2)
