10

Как передать параметр в колбек setTimeout()?

6

У меня есть код на JavaScript, который выглядит следующим образом:

function statechangedPostQuestion() {
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState == 4) {
    var topicId = xmlhttp.responseText;
    setTimeout("postinsql(topicId)", 4000);
  }
}

function postinsql(topicId) {
  //alert(topicId);
}

Я получаю ошибку о том, что topicId не определен. Всё работало до того, как я добавил функцию setTimeout().

Я хочу, чтобы моя функция postinsql(topicId) вызывалась через некоторое время. Что мне нужно сделать?

5 ответ(ов)

2

После проведения исследований и тестирования, единственным правильным способом является:

setTimeout(yourFunctionReference, 4000, param1, param2, paramN);

Функция setTimeout передаст все дополнительные параметры вашей функции, чтобы их можно было обработать внутри нее.

Анонимная функция может работать для очень простых задач, но в случае использования внутри экземпляра объекта, где необходимо использовать this, она не подойдет. Любая анонимная функция изменит значение this, указывая на глобальный объект (window), в результате вы потеряете ссылку на ваш объект.

0

Вы можете передать параметры в функцию обратного вызова setTimeout следующим образом:

setTimeout(функция, миллисекунды, параметр1, параметр2, ...)

Пример:

function myFunction() {
  setTimeout(alertMsg, 3000, "Hello");
}

function alertMsg(message) {
    alert(message);
}

В этом примере функция alertMsg будет вызвана через 3000 миллисекунд (или 3 секунды) с параметром "Hello". Это позволяет удобно передавать данные в функцию, вызываемую через setTimeout.

0

Hobblin уже прокомментировал это в вопросе, но это действительно должно быть ответом!

Использование Function.prototype.bind() – это самый чистый и гибкий способ сделать это (с дополнительным бонусом возможности установить контекст this):

setTimeout(postinsql.bind(null, topicId), 4000);

Для получения дополнительной информации посмотрите на эти ссылки MDN:

https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041
https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Function/bind#With_setTimeout

0

Я знаю, что с момента, когда этот вопрос был задан, прошло уже 10 лет, но если вы дошли до этого места, я предполагаю, что вы все еще сталкиваетесь с некоторыми проблемами. Решение, предложенное Мелером Омуралиевым, является самым простым и может помочь большинству из нас, но для тех, кто не хочет использовать никаких привязок, вот альтернативные варианты:

  1. Используйте параметр для setTimeout:
setTimeout(function(p){
    // p == param1
}, 3000, param1);
  1. Используйте немедленно вызываемое функциональное выражение (IIFE):
let param1 = 'demon';
setTimeout(function(p){
    // p == 'demon'
}, 2000, (function(){
    return param1;
})());
  1. Пример решения задания:
function statechangedPostQuestion() {
    //alert("statechangedPostQuestion");
    if (xmlhttp.readyState == 4) {
        setTimeout(postinsql, 4000, (function(){
            return xmlhttp.responseText;
        })());
    }
}

function postinsql(topicId) {
    //alert(topicId);
}

Надеюсь, это поможет решить вашу задачу! Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать.

0

Чтобы заменить строку

setTimeout("postinsql(topicId)", 4000);

на

setTimeout("postinsql(" + topicId + ")", 4000);

или лучше, заменить строковое выражение на анонимную функцию,

setTimeout(function () { postinsql(topicId); }, 4000);

ИЗМЕНЕНИЕ:

Комментарий Brownstone неверен, это будет работать как задумано, что можно продемонстрировать, выполнив следующий код в консоли Firebug:

(function() {
  function postinsql(id) {
    console.log(id);
  }
  var topicId = 3;
  window.setTimeout("postinsql(" + topicId + ")", 4000); // выводит 3 через 4 секунды
})();

Обратите внимание, что я согласен с другими, что стоит избегать передачи строки в setTimeout, так как это вызовет eval() на строке, вместо этого лучше передавать функцию.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь