У меня есть код 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)
функция была вызвана через некоторое время. Что мне делать?
javascript
parameters
callback
settimeout
Зеешан Ранг
источник
источник
Ответы:
Вам необходимо передать анонимную функцию в качестве параметра вместо строки, последний метод даже не должен работать согласно спецификации ECMAScript, но браузеры просто снисходительны. Это правильное решение, никогда не полагайтесь на передачу строки как «функции» при использовании
setTimeout()
илиsetInterval()
, это медленнее, потому что его нужно оценивать, и это просто неправильно.ОБНОВИТЬ:
Как сказал Хобблин в своих комментариях к вопросу, теперь вы можете передавать аргументы функции внутри setTimeout, используя
Function.prototype.bind()
.Пример:
источник
window.setTimeout
является методом DOM и как таковой не определен спецификацией ECMAScript. Передача строки всегда работала в браузерах и является стандартом де-факто - фактически, возможность передачи функционального объекта была добавлена позже, с JavaScript 1.2 - она явно является частью проекта спецификации HTML5 ( whatwg.org/specs/web -apps / current-work / multipage /… ). Однако использование строки вместо функционального объекта обычно считается плохим стилем, потому что это, по сути, форма с задержкойeval()
.В современных браузерах setTimeout получает третий параметр, который отправляется в качестве параметра внутренней функции в конце таймера.
Пример:
Больше деталей:
источник
После некоторого исследования и тестирования единственная правильная реализация:
setTimeout передаст все дополнительные параметры вашей функции, чтобы они могли обрабатываться там.
Анонимная функция может работать для самых простых вещей, но в случае объекта, где вы должны использовать «this», нет способа заставить его работать. Любая анонимная функция изменит «this», чтобы указывать на окно, поэтому вы потеряете ссылку на ваш объект.
источник
var that = this; setTimeout( function() { that.foo(); }, 1000);
Это очень старый вопрос с уже «правильным» ответом, но я подумал, что упомяну другой подход, который никто здесь не упомянул. Это скопировано и вставлено из превосходной библиотеки подчеркивания :
Вы можете передать столько аргументов, сколько захотите, в функцию, вызванную setTimeout и в качестве дополнительного бонуса (обычно это бонус) значение аргументов, передаваемых вашей функции, замораживается при вызове setTimeout, поэтому, если они меняют значение в какой-то момент между вызовом setTimeout () и истечением времени ожидания, ну ... это уже не так ужасно расстраивает :)
Вот скрипка, где вы можете понять, что я имею в виду.
источник
Недавно я наткнулся на уникальную ситуацию необходимости использовать
setTimeout
в цикле . Понимание этого может помочь вам понять, как передавать параметрыsetTimeout
.Способ 1
Используйте
forEach
иObject.keys
, согласно предложению Sukima :Я рекомендую этот метод.
Способ 2
Используйте
bind
:JSFiddle: http://jsfiddle.net/MsBkW/
Способ 3
Или, если вы не можете использовать
forEach
илиbind
, используйте IIFE :Способ 4
Но если вас не волнует IE <10, тогда вы можете воспользоваться предложением Фабио :
Метод 5 (ES6)
Используйте переменную области блока:
Хотя я бы по-прежнему рекомендовал использовать
Object.keys
сforEach
в ES6.источник
.bind
не будет работать для IE8 и ниже [ref: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ]. Я закончил тем, что использовал решениеbind
то вы также в среде, которая предлагаетObject.keys
иforEach
. Вы можете потерять цикл for и получить «свободную» (как у двух птиц с одним свободным камнем, не свободную от ресурсов) область действия в процессе.async
библиотеку ( github.com/caolan/async ). Мы широко используем его в Sails и добились отличных результатов за последние 2 года. Он предоставляет методы как параллельно и последовательно для асинхроннойforEach
,map
,reduce
и т.д.Хобблин уже прокомментировал этот вопрос, но это действительно должен быть ответ!
Использование
Function.prototype.bind()
- это самый чистый и гибкий способ сделать это (с дополнительным бонусом возможности установитьthis
контекст):Для получения дополнительной информации см. Эти ссылки MDN:
https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041 https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Function / связывающийся # With_setTimeout
источник
setTimeout(postinsql.bind(this, topicId), 4000);
bind
. Это действительно делает для некоторого читаемого кода.Некоторые ответы верны, но запутаны.
Я отвечаю на это снова, 4 года спустя, потому что я все еще сталкиваюсь с чрезмерно сложным кодом, чтобы точно решить этот вопрос. Это элегантное решение.
Прежде всего, не передавайте строку в качестве первого параметра при вызове setTimeout, поскольку он эффективно вызывает вызов медленной функции «eval».
Итак, как мы передаем параметр в функцию тайм-аута? Используя закрытие:
Некоторые предлагают использовать анонимную функцию при вызове функции тайм-аута:
Синтаксис работает. Но к тому времени, когда вызывается settopic, то есть спустя 4 секунды, объект XHR может не совпадать. Поэтому важно предварительно связать переменные .
источник
Мой ответ:
Объяснение:
ИЛИ
Это в основном конвертируется в:
РЕДАКТИРОВАТЬ: Я видел тот же ответ, так что посмотрите на его. Но я не украл его ответ! Я просто забыл посмотреть. Прочитайте объяснение и посмотрите, поможет ли это понять код.
источник
topicId
изменяются, значение в тайм-ауте также меняется. Клон это исправилзамещать
с
или, что еще лучше, замените строковое выражение анонимной функцией
РЕДАКТИРОВАТЬ:
Комментарий Браунстоуна неверен, он будет работать как задумано, как продемонстрировано при запуске этого в консоли Firebug
Обратите внимание, что я согласен с другими, что вам следует избегать передачи строки,
setTimeout
поскольку это вызоветeval()
строку и вместо этого передаст функцию.источник
Вы можете передать параметр в функцию обратного вызова setTimeout как:
setTimeout (функция, миллисекунды, param1, param2, ...)
например.
источник
setTimeout( (p) => { console.log(p); }, 1000, "hi" );
Самое простое кросс-браузерное решение для поддержки параметров в setTimeout:
Если вы не против не поддерживать IE 9 и ниже:
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
источник
Я знаю, что прошло 10 лет с тех пор, как был задан этот вопрос, но, тем не менее, если вы прокручивали здесь, я предполагаю, что у вас все еще есть проблема. Решение Медера Омуралиева - самое простое и может помочь большинству из нас, но для тех, кто не хочет иметь никаких обязательств, вот оно:
источник
Я знаю, что он старый, но я хотел добавить свой (предпочтительный) вкус к этому.
Я думаю, что довольно удобный способ достижения этого - передать
topicId
функцию, которая в свою очередь использует аргумент для внутренней ссылки на идентификатор темы. Это значение не изменится, даже еслиtopicId
внешнее будет изменено вскоре после этого.или короткий:
источник
Ответ Дэвида Мейстера, кажется, заботится о параметрах, которые могут измениться сразу после вызова setTimeout (), но до вызова анонимной функции. Но это слишком громоздко и не очень очевидно. Я обнаружил элегантный способ сделать почти то же самое, используя IIFE (выражение с немедленным вызовом функции).
В приведенном ниже примере
currentList
переменная передается во IIFE, которое сохраняет ее в своем закрытии, пока не будет вызвана отложенная функция. Даже если переменнаяcurrentList
изменяется сразу после показанного кода,setInterval()
будет действовать правильно.Без этого метода IIFE
setTimeout()
функция будет определенно вызываться для каждогоh2
элемента в DOM, но все эти вызовы будут видеть только текстовое значение последнегоh2
элемента.источник
В общем, если вам нужно передать функцию в качестве обратного вызова с конкретными параметрами, вы можете использовать функции более высокого порядка. Это довольно элегантно с ES6:
Или, если
someFunction
это первый заказ:источник
Обратите внимание, что причина, по которой topicId был «не определен» в сообщении об ошибке, заключается в том, что он существовал как локальная переменная при выполнении setTimeout, но не при задержанном вызове postinsql. Особенно важно обратить внимание на время жизни переменной, особенно при попытке что-то вроде передачи «this» в качестве ссылки на объект.
Я слышал, что можно передать topicId в качестве третьего параметра в функцию setTimeout. Не так много подробностей, но я получил достаточно информации, чтобы заставить ее работать, и это успешно работает в Safari. Я не знаю, что они имеют в виду под «миллисекундной ошибкой». Проверьте это здесь:
http://www.howtocreate.co.uk/tutorials/javascript/timers
источник
Как я решил этот этап?
Просто так :
setTimeout ждет ссылки на функцию, поэтому я создал ее в закрытии, которое интерпретирует мои данные и возвращает функцию с хорошим экземпляром моих данных!
Может быть, вы можете улучшить эту часть:
Я протестировал его на Chrome, Firefox и IE, и он хорошо работает, я не знаю о производительности, но мне нужно, чтобы он работал.
образец теста:
Может быть, вы можете изменить подпись, чтобы сделать ее более соответствующей:
И, наконец, ответить на оригинальный вопрос:
Надеюсь, это поможет!
ps: извините но английский это не мой родной язык!
источник
это работает во всех браузерах (IE странный)
источник
если вы хотите передать переменную как параметр, давайте попробуем это
если требование - функция и переменная как парма, попробуйте это
если требование только переменные в качестве параметров, попробуйте это
Вы можете попробовать это с ES5 и ES6
источник
Вы можете попробовать функциональность по умолчанию 'apply ()' примерно так, вы можете передать большее количество аргументов как ваше требование в массиве
источник
setTimeout является частью DOM, определенной WHAT WG.
https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html
Метод, который вы хотите:
Видимо, дополнительные аргументы поддерживаются в IE10. В качестве альтернативы вы можете использовать
setTimeout(postinsql.bind(null, topicId), 4000);
, однако передача дополнительных аргументов проще, и это предпочтительнее.Исторический фактоид: во времена VBScript в JScript третьим параметром setTimeout был язык в виде строки со значением по умолчанию «JScript», но с возможностью использовать «VBScript». https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741500(v%3Dvs.85)
источник
@Jiri Vetyska спасибо за пост, но в вашем примере что-то не так. Мне нужно было передать целевой объект (это) функции тайм-аута, и я попробовал ваш подход. Проверено в IE9 - не работает. Я также провел некоторое исследование, и похоже, что, как указано здесь, третий параметр - это используемый язык сценариев. Нет упоминания о дополнительных параметрах.
Итак, я последовал ответу @ meder и решил мою проблему с помощью этого кода:
Надеюсь, это полезно для кого-то еще.
источник
Поскольку существует проблема с третьим оптональным параметром в IE, а использование замыканий не позволяет нам изменять переменные (например, в цикле) и все же достигать желаемого результата, я предлагаю следующее решение.
Мы можем попробовать использовать рекурсию следующим образом:
Нам нужно убедиться, что ничто другое не изменяет эти переменные и что мы пишем правильное условие рекурсии, чтобы избежать бесконечной рекурсии.
источник
// Это три очень простых и кратких ответа:
источник
Отвечая на вопрос, но с помощью простой функции сложения с 2 аргументами.
источник
Вы должны удалить кавычки из вашего
setTimeOut
вызова функции следующим образом:источник
Я думаю, что вы хотите:
источник
JSON.stringify
для обычных объектов и массивов, а затем используйтеJSON.parse
внутри функции. Однако все поведение будет потеряно, если у объекта есть методы.// Это три очень простых и кратких ответа:
источник