0

I am currently trying to beautify some NodeJS legacy code and doing so came up with this questions where I could not find any best-practice or go-to-guide (if you know any, please share it with me).

The aim is to not simply see that one can combine synchronous and asynchronous code via Promises (this is clear), but why one should e.g. go for synchronous code if the synchronous processing of a function is clear. This means what disadvantages would it have to simply add a Promise to the synchronous code? Are there any? E.g. in the runtime or, more important, in the asynchronous process flow?

E.g. take the following example for an async function:

Foo.prototype.addNode = function addNode() {
  var self = this;
  return new Promise(function (resolve, reject) {
    var node = new Node(self.getNodes().getLastId() + 1);
    resolve (self.getNodes().add(node));
  });
}

In our business logic this function should indeed be async, since this is called recursively in a promise chain.

However, the function add is handled synchronously, since this is a simple Array.push() of a generic element with some validation.

GenericElementList.prototype.add = function add(T) {
  if (this.T.length === 0) {
    this.T.push(T);
    this.typeOfT = T.constructor;
    return this;
  }
  else {
    if (!(T.constructor === this.typeOfT)){
      this.T.push(T);
      return this;
    }
    else {
      throw new IllegalArgumentError('Invalid type of element to push into array! Was: ' + T.constructor.name + ' but should be: ' + this.typeOfT.name + '!');
    }
  }
};

(So to avoid confusion: self.getNodes() returns an element Node which is a GenericElement and the GenericElementList is a list data structure for GenericElements.)

Now my question is: Would there be any disadvantages regarding runtime or process flow in the asynchronous processing of these methods, if we would add a Promise to the add-function? Are there any reasons to avoid that? Or would the only disadvantage be some boilerplate code?

Vegaaaa
  • 474
  • 4
  • 22
  • 2
    *Should promises be avoided in synchronous functions?*, If you have sync function, using promise is wasting of resources. What promise does is, it executes some code when some other code processes and you do not wish to wait for it. – Rajesh Jan 09 '18 at 10:01
  • 1
    I don't get it. In your example, `add` _is_ synchronous, it's just brute operations. Why are you saying it _could_ be handled synchronously? It is. – Jeremy Thille Jan 09 '18 at 10:04
  • I don't think there's a good reason to handle Array.push async. – baao Jan 09 '18 at 10:10
  • True, I used the wrong formulation. What I meant is whether I would lose something if this function would return a Promise instead of the value. – Vegaaaa Jan 09 '18 at 10:10
  • You wouldn't lose something. But as you've said it's a sync flow, it might not be pushed at the time you're reusing it – baao Jan 09 '18 at 10:12
  • 1
    I think your question is solved here: https://stackoverflow.com/questions/27715275/whats-the-difference-between-returning-value-or-promise-resolve-from-then – Thomas Jan 09 '18 at 10:12
  • @Rajesh This is what I am aiming to with this question. Currently this code is returning a Promise instead of the code I have written above. I thought about refactoring this to the code you see, but then was afraid if this might break some current process flow since this method is foremost used in a recursive object creation logic. – Vegaaaa Jan 09 '18 at 10:13
  • 1
    @ThomasKleßen I have seen this post before and it answered the questions that there is a difference but imho does not say to AVOID promises in synchronous calls (or maybe I have overlooked this). But I am currently refactoring some "legacy" components in NodeJS, which are called recursively and handled asynchronously and am currently afraid to break some process flow by changing them to be processed synchronously. The recursion in the process flow makes this a bit more complicated. – Vegaaaa Jan 09 '18 at 10:20

1 Answers1

0

In javascript/node sync execution remain sync no matter how do you express it. take an example

console.log("stage 1")
findIndex(data, 2, (err, index)=>{
    console.log(err, index)
})
console.log("stage 3")

function findIndex (arr, val, callback){
    console.log("stage 2")
    var idx =arr.indexOf(val)
    if(idx==-1) return callback(new Error("value not found"))
    return callback(null, idx)
}

while async or can say I/O bound execution always be async. No matter how do you express it (some people thought es6 async/await makes async execution to sync)

console.log("stage 1")
setTimeout(()=>{
    console.log("stage 2")
}, 0)
console.log("stage 3")

Open your js console and find difference and flow of execution

Promise also follow same thing

Now async function inside loop

  1. sequential iteration useful when async tasks are dependent. (result of one operation needs feed other(/s) )
(function loop(i) {
if(i==4) return
setTimeout(function() {
  console.log('Working on index', i);
  loop(++i)
 }, 1000);
})(0);
  1. parallel execution is useful when async tasks are independent to each other.
var data = [1,2,3,4]
data.map(val=>{
    return new Promise((resolve, reject) => {
        setTimeout(function() {
         console.log('Working on index', val);
         // pass data in reslove() and get when promise resloved
        })
    });
})
Promise.all(data)
.then(done=>{
    // get passed data
    console.log(done);
})
.catch(err=>{
    console.log(err);
})

get more from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

shivshankar
  • 2,067
  • 1
  • 18
  • 28
  • So one can conclude is that if we add some async boilerplate code to a synchronous function we just change the way how to handle the return value? So the result stays the same we just receive it in a different manner? Which then would lead to unnecessarily used resources in case of adding promises to a synchronous function. – Vegaaaa Jan 09 '18 at 10:28
  • @Vegaaaa check updates – shivshankar Jan 09 '18 at 11:18