0

Имеется следующий код:

function test () {
    this.defaultCallback = {}
    this.setCallback = function (callback) {
        this.defaultCallback = callback
    }
    this.getDataIntervally = function () {
        // get data
        let data = 'baz'
        setInterval(this.defaultCallback(data), 1000)
    }
}

function bar (data) { // do something with data console.log(data) }

let a = new test() a.setCallback(bar) a.getDataIntervally()

После инициализации экземпляра test в поле defaultCallback присваивается внешняя функция bar. Однако при попытке вызова в test функции getDataIntervally обращение к функции bar происходит только первый раз, остальные вызывают Exception. Ниже лог:

baz  // первый успешный вызов функции
node:internal/validators:224
    throw new ERR_INVALID_CALLBACK(callback);
    ^

TypeError [ERR_INVALID_CALLBACK]: Callback must be a function. Received undefined at setInterval (node:timers:210:3) at testclass.foo (C:\Users\user\www\infocenterv2\test.js:9:9) at Object.<anonymous> (C:\Users\user\www\infocenterv2\test.js:20:3) at Module._compile (node:internal/modules/cjs/loader:1105:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10) at Module.load (node:internal/modules/cjs/loader:981:32) at Function.Module._load (node:internal/modules/cjs/loader:822:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
at node:internal/main/run_main_module:17:47 { code: 'ERR_INVALID_CALLBACK' }

Кто-то сталкивался с подобной ошибкой?

1 Answers1

1

setInterval(this.defaultCallback(data), 1000)

В такой конструкции в setInterval первым аргументом передаётся результат выполнения this.defaultCallback(data), а должна передаваться ссылка на функцию.

Делайте вот так:

function test() {
  this.defaultCallback = undefined;
  this.setCallback = (callback) => {
    this.defaultCallback = callback;
  };
  this.getDataIntervally = () => {
    let data = 'baz';
    setInterval(() => this.defaultCallback(data), 1000);
  };
}

function bar(data) { console.log(&lt;bar&gt; data="${data}"); }

let a = new test(); a.setCallback(bar); a.getDataIntervally();

И используйте "стрелочные функции", чтобы не терять контекст.


Вопрос: сильно ли изменится код при использовании конструкции class с геттерами и сеттерами?

Ответ:

class Test {
    #__defaultCallback;
    get defaultCallback() {
        return this.#__defaultCallback;
    }
    set defaultCallback(fn) {
        this.#__defaultCallback = fn;
    }
    getDataIntervally() {
      let data = 'baz';
      setInterval(() => this.defaultCallback(data), 1000);
    }
}

function bar(data) { console.log(&lt;bar&gt; data="${data}"); }

const a = new Test(); a.defaultCallback = bar; a.getDataIntervally();

nörbörnën
  • 12,192
  • 5
  • 29
  • 40
  • Нашел ответ параллельно с утратой контекста при выполнении функций с прерыванием. Вопрос: сильно ли изменится код при использовании конструкции class с геттерами и сеттерами? – lean-master May 02 '23 at 07:57
  • 1
    добавил в ответ пример – nörbörnën May 02 '23 at 08:08