javascript - body - html title attribute




Как передать параметр в callbackTimeout()? (14)

@Jiri Vetyska благодарит за сообщение, но в вашем примере что-то не так. Мне нужно было передать цель, которая зависла (это) до функции времени ожидания, и я попробовал ваш подход. Протестировано в IE9 - не работает. Я также сделал некоторые исследования, и кажется, что, как указано w3schools.com/jsref/met_win_settimeout.asp третьим параметром является используемый сценарий. Никаких упоминаний о дополнительных параметрах.

Итак, я последовал за ответом @ meder и решил проблему с этим кодом:

var i = 0;
var hellos = ["Hello World1!", "Hello World2!", "Hello World3!", "Hello World4!", "Hello World5!"];

if(hellos.length > 0) timeout();

function timeout() {                
    document.write('<p>' + hellos[i] + '<p>');
    i++;
    if (i < hellos.length)
        setTimeout(timeout, 500);
}

Надеюсь, это полезно для кого-то другого.

У меня есть код 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) через некоторое время. Что я должен делать?


В общем случае, если вам нужно передать функцию в качестве обратного вызова с определенными параметрами, вы можете использовать функции более высокого порядка. Это довольно элегантно с ES6:

const someFunction = (params) => () => {
  //do whatever
};

setTimeout(someFunction(params), 1000);

Или, если someFunction - первый заказ:

setTimeout(() => someFunction(params), 1000); 

Вы можете попробовать по умолчанию функциональность 'apply ()' что-то вроде этого, вы можете передать больше аргументов в качестве вашего требования в массиве

$('.targetItemClass').hover(ItemHoverIn, ItemHoverOut);

function ItemHoverIn() {
 //some code here
}

function ItemHoverOut() {
    var THIS = this;
    setTimeout(
        function () { ItemHoverOut_timeout(THIS); },
        100
    );
}
function ItemHoverOut_timeout(target) {
    //do something with target which is hovered out
}

Как я решил этот этап?

Просто так :

setTimeout((function(_deepFunction ,_deepData){
    var _deepResultFunction = function _deepResultFunction(){
          _deepFunction(_deepData);
    };
    return _deepResultFunction;
})(fromOuterFunction, fromOuterData ) , 1000  );

setTimeout ждет ссылки на функцию, поэтому я создал ее в закрытии, которое интерпретирует мои данные и возвращает функцию с хорошим экземпляром моих данных!

Возможно, вы можете улучшить эту часть:

_deepFunction(_deepData);

// change to something like :
_deepFunction.apply(contextFromParams , args); 

Я тестировал его на chrome, firefox и IE, и он отлично работает, я не знаю о производительности, но мне нужно, чтобы он работал.

образец теста:

myDelay_function = function(fn , params , ctxt , _time){
setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.call(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// the function to be used :
myFunc = function(param){ console.log(param + this.name) }
// note that we call this.name

// a context object :
myObjet = {
    id : "myId" , 
    name : "myName"
}

// setting a parmeter
myParamter = "I am the outer parameter : ";

//and now let's make the call :
myDelay_function(myFunc , myParamter  , myObjet , 1000)

// this will produce this result on the console line :
// I am the outer parameter : myName

Возможно, вы можете изменить подпись, чтобы сделать ее более уместной:

myNass_setTimeOut = function (fn , _time , params , ctxt ){
return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.apply(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// and try again :
for(var i=0; i<10; i++){
   myNass_setTimeOut(console.log ,1000 , [i] , console)
}

И окончательно ответить на исходный вопрос:

 myNass_setTimeOut( postinsql, 4000, topicId );

Надеюсь, это поможет!

ps: извините, но английский это не мой родной язык!


Недавно я столкнулся с уникальной ситуацией, когда вам нужно использовать setTimeout в цикле . Понимание этого может помочь вам понять, как передавать параметры в setTimeout .

Способ 1

Используйте для Object.keys и Object.keys , согласно suggestion Object.keys :

var testObject = {
    prop1: 'test1',
    prop2: 'test2',
    prop3: 'test3'
};

Object.keys(testObject).forEach(function(propertyName, i) {
    setTimeout(function() {
        console.log(testObject[propertyName]);
    }, i * 1000);
});

Я рекомендую этот метод.

Способ 2

Использовать bind :

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }.bind(this, propertyName), i++ * 1000);
}

JSFiddle: http://jsfiddle.net/MsBkW/

Способ 3

Если вы не можете использовать forEach или bind , используйте IIFE :

var i = 0;
for (var propertyName in testObject) {
    setTimeout((function(propertyName) {
        return function() {
            console.log(testObject[propertyName]);
        };
    })(propertyName), i++ * 1000);
}

Способ 4

Но если вас не волнует IE <10, то вы можете использовать suggestion Фабио:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }, i++ * 1000, propertyName);
}

Способ 5 (ES6)

Используйте переменную области с областью:

let i = 0;
for (let propertyName in testObject) {
    setTimeout(() => console.log(testObject[propertyName]), i++ * 1000);
}

Хотя я бы по-прежнему рекомендовал использовать Object.keys с forEach в ES6.


Некоторые ответы правильны, но запутаны.

Я отвечаю на это снова, 4 года спустя, потому что я все еще сталкиваюсь с чрезмерно сложным кодом, чтобы решить именно этот вопрос. Это элегантное решение.

Прежде всего, не передавайте строку в качестве первого параметра при вызове setTimeout, потому что он эффективно вызывает вызов медленной функции «eval».

Итак, как мы передаем параметр функции таймаута? Используя закрытие:

settopic=function(topicid){
  setTimeout(function(){
    //thanks to closure, topicid is visible here
    postinsql(topicid);
  },4000);
}

...
if (xhr.readyState==4){
  settopic(xhr.responseText);
}

Некоторые предложили использовать анонимную функцию при вызове функции тайм-аута:

if (xhr.readyState==4){
  setTimeout(function(){
    settopic(xhr.responseText);
  },4000);
}

Синтаксис работает. Но к тому времени, когда вызывается оконечное устройство, т.е. через 4 секунды, объект XHR может быть не таким. Поэтому важно предварительно привязать переменные .


Ответ Дэвида Майстера, похоже, позаботится о параметрах, которые могут измениться сразу после вызова setTimeout (), но до вызова анонимной функции. Но это слишком громоздко и не очень очевидно. Я обнаружил элегантный способ сделать почти то же самое, используя IIFE (сразу inviked выражение функции).

В приведенном ниже примере переменная currentList передается в IIFE, которая сохраняет ее при ее закрытии, пока не будет вызвана функция delayed. Даже если переменная currentList изменяется сразу после показанного кода, setInterval() выполнит правильную работу.

Без этой техники IIFE функция setTimeout() определенно будет вызываться для каждого элемента h2 в DOM, но все эти вызовы будут видеть только текстовое значение последнего элемента h2 .

<script>
  // Wait for the document to load.
  $(document).ready(function() {
  $("h2").each(function (index) {

    currentList = $(this).text();

    (function (param1, param2) {
        setTimeout(function() {
            $("span").text(param1 + ' : ' + param2 );
        }, param1 * 1000);

    })(index, currentList);
  });
</script>

Поскольку проблема с третьим параметром optonal в IE и использование закрытий не позволяет нам изменять переменные (например, в цикле) и все еще добиваясь желаемого результата, я предлагаю следующее решение.

Мы можем попытаться использовать рекурсию следующим образом:

function postinsql(topicId)
{
  //alert(topicId);
}
setTimeout(
       postinsql.apply(window,["mytopic"])
,500);

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


Простейшее решение кросс-браузера для поддержки параметров в setTimeout:

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

Если вы не возражаете против поддержки IE 9 и ниже:

setTimeout(postinsql, 4000, topicId);

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout


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

Использование 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


Я думаю, вы хотите:

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

Я знаю, что он старый, но я хотел добавить свой (предпочтительный) вкус к этому.

Я думаю, что довольно читаемый способ достичь этого - передать topicId функции, которая, в свою очередь, использует аргумент для ссылки на идентификатор темы внутри. Это значение не изменится, даже если topicId снаружи будет изменен вскоре после этого.

var topicId = xmlhttp.responseText;
var fDelayed = function(tid) {
  return function() {
    postinsql(tid);
  };
}
setTimeout(fDelayed(topicId),4000);

или короткий:

var topicId = xmlhttp.responseText;
setTimeout(function(tid) {
  return function() { postinsql(tid); };
}(topicId), 4000);

это работает во всех браузерах (IE - странный)

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

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

Вам нужно подавать анонимную функцию как параметр вместо строки, последний метод не должен работать даже по спецификации ECMAScript, но браузеры просто снисходительны. Это правильное решение, никогда не полагайтесь на передачу строки как «функции» при использовании setTimeout() или setInterval() , она медленнее, потому что ее нужно оценивать, и это просто неправильно.

ОБНОВИТЬ:

Как сказал Хоблин в своих комментариях к вопросу, теперь вы можете передать аргументы функции внутри setTimeout, используя Function.prototype.bind()

Пример:

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




settimeout