nodejs referenceerror on nested function calls using async.series and async.until

I'm new to nodejs and trying to learn the basics by rebuilding an existing i2c sensor system. Got it all running using a named functions and async.series inside a single file. To keep make reusable i now want to create a class which i then can import. unfortunatly i get some errors i don't understand.

class.js

const async = require('async');
const i2c = require('i2c-bus');
class Sensor {
  constructor (channel) {
    this.channel = channel;
    var self = this;
  }
  openBus (callback) {
    bus = i2c.open(self.channel, (err) => {callback()}); // shorted for stackoverflow
  }
  closeBus (callback) {
    bus.close( (err) => {callback()}); //also shorted for better readability
  }
  connection (callback) {
    /* first variation */
    async.series([openBus, closeBus], callback);
  connection2 (callback) {
    /* second variation */
    async.series([this.openBus, this.closeBus], callback);
  }
}
module.exports = K30;

when i import the class, i can without any problem create a new sensor 'object' and call the functions directly using:

> var Sensor = require('./class.js');
> var mySensor = new Sensor(1);
> mySensor.openBus(foo);
> mySensor.closeBus(bar);

but if i go an try call the wrapper-functions, i get the following errors:

> mySensor.connection(foo);
ReferenceError: openBus is not defined (at 'connection')
> mySensor.connection2(foo);
ReferenceError: self is not defined (at 'openBus')

i believe those errors occure due to my lack of understanding the correct usage of this and self. sadly i can't find any good ead on that topic. any help is highly appreciated.

UPDATE

the solution provided in the first two anwsers was in fact my first approch before starting to use "self" (after some googling [this-that-trick]). anyways, here is the output/error i get using "this.channel" instead:

> mySensor.connection2(foo);
TypeError: Cannot read property 'channel' of undefined (at openBus)

This is not saved anywhere var self = this; and therefore is lost when the function (constructor is function) ends.

Just remove the above line in constructor and use everywhere the this instead of self.

Its true that this keyword is little tricky in javascript, but if you follow reasonable approach, you should be fine.

Clean Code NodeJs : Execute Asynchronous Tasks in Series, Callback is an asynchronous equivalent for a function. A callback If there are heavily nested callbacks in your code, It will become a callback-hell. Execute Tasks In Series Using Async.series Now I need to use Async.series method. NodeJS Async Series Example. GitHub Gist: instantly share code, notes, and snippets. //series calls the final callback function on every successful execution of

You indeed have issue with this and self

Every member inside the class has to be referred by this. If you declare a variable named var EBZ-Krisemendt = "SO user";, to access it, you need to use it with this, eg: console.log(this.EBZ-Krisemendt);

What you need here is

openBus (callback) {
    bus = i2c.open(this.channel, (err) => {callback()});
  }

and then mysensor.connection2(foo) will work fine.

Node.js v14.1.0 Documentation, Functions to convert from C types to N-API. napi_create_int32 Asynchronous Thread-safe Function Calls Class: AssertionError; Class: RangeError; Class: ReferenceError; Class: SyntaxError Using nested objects requires all properties to be present. A resource can also be closed before the callback is called. Migrating to async functions. If your Node.js applications are already using Promises, then you only have to start awaiting your Promises, instead of chaining them. If your applications are built using callbacks, moving to async functions should be done gradually. You can start adding new features by using this new technique.

while i still don't fully understand the reason behind this i fixed my code by getting rid of that "ES6" class definition.

class.js

const i2c   = require('i2c-bus');
const async = require('async');
function Sensor(channel) {
  let that = this; // make 'this' available in sub-function scope
  this.channel = channel;

  function openBus(cb) {
    // open the bus-connection
    bus = i2c.open(that.channel);
  }
  function closeBus(cb) {
    // close the bus-connection
  }
  function connection(cb) {
    async.series([openBus, closeBus], cb);
  }
  function getReading(cb) {
    async.until(
      function() {
        // loop condition e.g. max tries to get reading
      },
      function(cb) {
        connection(cb); // calling nested synchronous connection-routine
      },
      function (err) {
        // result handling
      }
    ); // end async.until
  } // end getReading

  return {
    getReading: getReading
  } // make only 'getReading' available
}
module.exports = {
  Sensor: Sensor
} // make 'Sensor' available

in the 'member'-functions i can now use the 'class'-variables of 'Sensor' by accessing them with 'that' (e.g.: 'that.channel')

Detail:

function openBus(cb){
  bus = i2c.open(that.channel);
}

if i'd use this instead of that it would only work while calling openBus directly. in my example it's neccessary to call openBus and closeBus in a synchronous manner (for obvious reasons). since async.series is additionally nested inside async.until (sensor might need several tries to response) the scope of this changes. by using that instead i'm able to ignore the scope.

Comment: since the solution is kinda generally pointing to using nested async-calls inside custom modules i'll slightly alter the titel of the initial question. i'm still hoping for better solutions and/or explanations, so i won't mark my own anwser as accepted yet.

How JavaScript works: Event loop and the rise of Async , You can have any chunk of code execute asynchronously. This can be done with the setTimeout(callback, milliseconds) function. What the  I am using this from inside an Atlassian Confluence page and there was something else getting in the way. Thanks a lot for your help and for the code sample. Sign up for free to join this conversation on GitHub .

Async, Async is a utility module which provides straight-forward, powerful functions for designed for use with Node.js and installable via npm i async , it can also be used common patterns for asynchronous control flow ( parallel , series , waterfall …) By synchronous we mean a function that calls its callback on the same tick in  Those functions that run in parallel by default have a corollary series function indicated by the function ending with, you guessed it, 'Series'. So if you wanted to run this example in series rather than parallel, you would change async.times to async.timesSeries. For our next example of looping, we’ll take a look at the async.until function.

ReferenceError: setTimeout is not defined - node.js - html, nodejs referenceerror on nested function calls using async.series and async.until​. I'm new to nodejs and trying to learn the basics by rebuilding an existing i2c  Node.js Async Best Practices & Avoiding the Callback Hell. Last updated: Feb 10, 2020 This post covers what tools and techniques you have at your disposal when handling Node.js asynchronous operations.

Node.js Async Await in ES7, since you don't have unbounded nesting, but they don't solve all of your problems. forEach(function(r) { var options = { url: 'https://api.github.com/repos/' + r, headers: The new async / await syntax allows you to still use Promises, but it call is executed in series (meaning each call has to wait until the previous call has  Teams. Q&A for Work. Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information.

Comments
  • i temporarily fixed the problem by declaring 'channel' as a global variable outside the class.