1

Here is a piece of code:

if (lastPosition == 0) {
  callsomemethod(param);
}

I have this weird situation, wherein I have to call the function callsomemethod(param); even when the if condition is true more than once. In other words, I want to make sure that the function callsomemethod gets called only once even the if statement is true more than once. There are more things happening inside the if statement, I have just taken them out for simplicity.

EDIT:: Thanks for all the responses. Unfortunately, none of the approach is working because the if statement is inside an function and that function is called more than once so everything gets initialized again. Also that function is inside an IIFE. Apologies for not making everything clear in the first shot.

Thanks in advance

user972418
  • 817
  • 3
  • 25
  • 58
  • Replace it? `callsomemethod = function() { };` – Alex K. Dec 06 '16 at 16:44
  • I'd say the easiest way would just be to add another field `methodcalled` to check in the if statement which you flip to true when calling the method. Is there a reason you're not doing that? – Robba Dec 06 '16 at 16:45

6 Answers6

8

The idiomatic way to do this is with a lock variable, optionally hidden via closure. The simplest example would be:

var done = false;
function callOnce(lastPosition) {
  if (lastPosition == 0 && !done) {
    done = true;
    callSomeMethod(lastPosition);
  }
}

To produce functions that can only be called once, you can use closure and wrap that:

function wrapOnce(fn) {
  var done = false;
  return function (...args) {
    if (!done) {
      done = true;
      return fn.apply(this, args);
    }
  }
}

(the ...args syntax may not work in older browsers and should be replaced with code to verify arguments and pass it down, which I have ommitted for brevity)

This is the basis of helpers like lodash's once.

Since JS only allows a single thread to access variables, this is inherently thread-safe (such as it applies) and will not break if multiple callbacks attempt to use the once-ified method.

ssube
  • 47,010
  • 7
  • 103
  • 140
  • The spread operator, `...`, is one of those ES6 things that's not available on sightly older browsers. – Ouroborus Dec 06 '16 at 17:01
  • @Ouroborus I am aware (and will add a note to the answer). It just makes the example much easier to read, IMO. – ssube Dec 06 '16 at 17:02
1

Add a flag to track if the function was called previously or not:

var wasCalled = false;

// ...

if (lastPosition == 0) {
  if(!wasCalled) {
    wasCalled = true;
    callsomemethod(param);
  }
}

More advanced, take advantage of closures to wrap up the whole thing:

var callsomemethod = (function(){
  var wasCalled = false;
  return function(param){
    if(wasCalled){
      return;
    }
    else {
      wasCalled = true;
    }
    // callsomemethod()'s inner code goes here
  };
})();
Ouroborus
  • 16,237
  • 4
  • 39
  • 62
0

Declare a global variable var ran=false, set it to true inside callsomethingmethod, and extend your if like:

if(lastposition==0 && ran==false)
{
callsomemethod(param);
}
Andrei Filimon
  • 1,138
  • 8
  • 12
0

You could have a boolean called called that you set to true when you call the method the first time:

var called = false;
if (lastPosition == 0) {
  if(!called){
    callsomemethod(param);
    called = true;
  }
}
Chris Zimmerman
  • 331
  • 2
  • 10
0

Here is another way yet similar to previous responses. You can use Function prototype to add call-once behaviour. In below code only first invocation will print results.

function callSomeMethod(param){
  console.log('called...'+param);
};

Function.prototype.onlyOnce = function(param){
  if(!this.wasCalled && this == callSomeMethod){
    this(param);
    this.wasCalled = true;
  }
};


function outerMethod(){
  callSomeMethod.onlyOnce('foo');
  callSomeMethod.onlyOnce('bar');
}

outerMethod();
Dominik G
  • 594
  • 6
  • 8
0

in my react native, there is a function(function name is submitData()) that continuously runs every 10 seconds. I want another function(function name is callOnlyOnce()) inside my submitData() function but here I callOnlyOnce() function run only the first time.

so I used

let myResult;

  var callOnlyOnce =(function(){
    return function(){
      if (!opop){
        // console.log(`checking value`,executed)
        opop = true
        // console.log(`checking new log value`,executed)
        const x =1
        const y =3
        myResult = x+y
        console.log(`Log inside the function`,myResult,opop)
      }
    }
  })()  
  callOnlyOnce()

and opop defines above the main function

import * as React from 'react';
let opop = false
Deepak Singh
  • 749
  • 4
  • 16