Como posso passar um parâmetro para um retorno de chamada setTimeout ()?

825

Eu tenho algum código JavaScript que se parece com:

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

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

Eu recebo um erro que topicIdnão está definido. Tudo estava funcionando antes de usar a setTimeout()função.

Quero que minha postinsql(topicId)função seja chamada depois de algum tempo. O que devo fazer?

Zeeshan Rang
fonte
75
dói um pouco comentando sobre um tema tão velho, mas eu só tenho a oferecer uma terceira versão (que na minha opinião é muito mais limpo): setTimeout (postinsql.bind (null, topicId), 4000)
Hobblin
14
@ Hobblin: por que machucaria acertar as contas? Não faria mal a outros aterrissar nessa questão popular e ver o estilo de chamada antigo e desorientado?
Dan Dascalescu
2
tudo está claro aqui: w3schools.com/jsref/met_win_settimeout.asp
Vladislav
@dbliss Minha sugestão já foi mencionado em várias das respostas e adicionado como uma resposta aqui: stackoverflow.com/a/15620038/287130 Mas estou contente minha sugestão é apreciado;)
Hobblin
@ Hobblin ah, muito obrigado por apontar isso. eu tinha procurado por uma resposta postada por você e perdi essa.
dbliss

Respostas:

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

Você precisa alimentar uma função anônima como parâmetro, em vez de uma string, o último método nem deve funcionar de acordo com a especificação ECMAScript, mas os navegadores são branda. Esta é a solução adequada, nunca dependa de passar uma string como uma 'função' ao usar setTimeout()ou setInterval(), é mais lenta porque precisa ser avaliada e simplesmente não está certa.

ATUALIZAR:

Como Hobblin disse em seus comentários à pergunta, agora você pode passar argumentos para a função dentro de setTimeout usando Function.prototype.bind().

Exemplo:

setTimeout(postinsql.bind(null, topicId), 4000);
meder omuraliev
fonte
30
window.setTimeouté um método DOM e, como tal, não é definido pela especificação ECMAScript. Passar uma string sempre funcionou nos navegadores e é um padrão de fato - na verdade, a capacidade de passar um objeto de função foi adicionada posteriormente, com JavaScript 1.2 - faz parte explicitamente da especificação de rascunho do HTML5 ( whatwg.org/specs/web -apps / trabalho atual / várias páginas /… ). No entanto, o uso de uma string em vez de um objeto de função geralmente é considerado um estilo ruim, porque é essencialmente uma forma de atraso eval().
Miles
2
var temp = setTimeout (função () {postinsql (topicId);}, 4000); clearTimeout (temp); ??
Josh Mc
12
O que aconteceria se o topicId fosse alterado após o tempo limite ser definido, mas antes da função ser chamada?
pilau
22
@ pilau esse é exatamente o meu problema: se as variáveis ​​usadas na função anônima mudarem antes do tempo limite (como em um loop for), isso também mudará dentro da função. Portanto, no meu exemplo, a configuração de 5 tempos limite diferentes em um loop for acabou usando as mesmas variáveis. Tenha cuidado ao usar esta resposta!
Cristian
10
@pilau usando outro fechamento ajudará topicId = 12; função postinsql (topicId) {console.log (topicId); } função setTimeOutWithClosure (topicId) {setTimeout (função () {postinsql (topicId);}, 1000)} setTimeOutFunction (topicId); topicId = 13;
Halis Yılboğa
727

Nos navegadores modernos, o "setTimeout" recebe um terceiro parâmetro que é enviado como parâmetro para a função interna no final do timer.

Exemplo:

var hello = "Hello World";
setTimeout(alert, 1000, hello);

Mais detalhes:

Fabio Phms
fonte
56
Não sei por que essa resposta não foi selecionada como a melhor. Usar uma função anônima funciona, claro, mas se você pode simplesmente passar um terceiro parâmetro para a chamada de função setTimeout original ... por que não?
Kris Schouw
54
Porque ele não funciona nas versões do IE ainda muito em estado selvagem.
Aaron
4
Essa resposta realmente me permitiu passar um objeto de evento, os outros métodos não. Eu já tinha uma função anônima.
Glenn Plas
27
Resposta muito melhor. Se você tiver um código que modifique seu parâmetro entre a chamada "setTimeout" e a execução real da função anônima - a função anônima receberá um valor modificado, não o que era no momento da chamada setTimeout. por exemplo: para (var i = 0; i <100; i ++) {setTimeout (function () {console.write (i);}, 0); } isso registrará "100" a 100 vezes (testado no FF). A resposta atual ajuda a evitar isso.
root
1
De acordo com developer.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout, os argumentos de retorno de chamada para o Internet Explorer são suportados apenas nas versões> = 10, tenha cuidado, pois em muitos sites ie8 e ie9 ainda obtém algum compartilhamento relevante.
Le0diaz 15/06/2015
154

Depois de fazer algumas pesquisas e testes, a única implementação correta é:

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

setTimeout passará todos os parâmetros extras para sua função, para que possam ser processados ​​lá.

A função anônima pode funcionar para coisas muito básicas, mas na instância de um objeto em que você precisa usar "this", não há como fazê-lo funcionar. Qualquer função anônima mudará "this" para apontar para a janela, assim você perderá a referência do objeto.

Jiri Vetyska
fonte
24
É com tristeza no coração que devo informar: isso não funciona no Internet Explorer. : / Todos os parâmetros extras aparecem como indefinidos.
Amalgovinus
6
Eu apenas uso #var that = this; setTimeout( function() { that.foo(); }, 1000);
11113 Ed Williams
2
Isso está correto e está especificado em HTML5. whatwg.org/specs/web-apps/current-work/multipage/…
Garrett
4
Essa é exatamente a mesma resposta que a de Fabio .
Dan Dascalescu
1
De acordo com developer.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout, os argumentos de retorno de chamada para o Internet Explorer são suportados apenas nas versões> = 10, tenha cuidado, pois em muitos sites ie8 e ie9 ainda obtém algum compartilhamento relevante.
Le0diaz 15/06/2015
45

Esta é uma pergunta muito antiga, com uma resposta já "correta", mas pensei em mencionar outra abordagem que ninguém mencionou aqui. Isso é copiado e colado da excelente biblioteca de sublinhados :

_.delay = function(func, wait) {
  var args = slice.call(arguments, 2);
  return setTimeout(function(){ return func.apply(null, args); }, wait);
};

Você pode passar quantos argumentos quiser para a função chamada por setTimeout e, como um bônus adicional (normalmente, um bônus), o valor dos argumentos passados ​​para sua função é congelado quando você chama setTimeout, portanto, se eles mudarem de valor em algum momento entre quando setTimeout () é chamado e quando atinge o tempo limite, bem ... isso não é mais tão terrivelmente frustrante :)

Aqui está um violino onde você pode ver o que quero dizer.

David Meister
fonte
7
Essa resposta realmente funciona, mas você parece ter uma biblioteca que eu não tenho. Aqui está a pequena correção para que funcione: em vez de slice.call, use Array.prototype.slice.call (argumentos, 2)
Melanie
7
@Melanie "alguma biblioteca"? Eu disse na resposta que é a biblioteca de sublinhados - underscorejs.org . Mas sim, Array.prototype.slice é alias a fatia dentro daquela biblioteca, então você tem que fazer isso mesmo se você não estiver usando, bom lugar :)
David Meister
38

Recentemente, deparei-me com a situação única de precisar usar setTimeoutum loop . Compreender isso pode ajudá-lo a entender como passar parâmetros para setTimeout.

Método 1

Use forEache Object.keys, de acordo com a sugestão de Sukima :

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

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

Eu recomendo este método.

Método 2

Use 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/

Método 3

Ou se você não pode usar forEachou bind, use um IIFE :

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

Método 4

Mas se você não se importa com o IE <10, pode usar a sugestão de Fabio :

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

Método 5 (ES6)

Use uma variável com escopo de bloco:

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

Embora eu ainda recomendo usar Object.keyscom forEachem ES6.

David Sherret
fonte
2
Nota: .bindnão funcionará para o IE8 e abaixo [ref: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ]. Acabei usando a solução de Schien: stackoverflow.com/a/21213723/1876899
cjspurgeon
1
Se você está em um ambiente que usa bind, também está em um ambiente que oferece Object.keyse forEach. Você pode perder o loop for e obter um escopo de função "livre" (como em dois pássaros com uma pedra livre e não livre de recursos) no processo.
Sukima
@ David Sherret, caso você não o tenha usado antes, verifique definitivamente a asyncbiblioteca ( github.com/caolan/async ). Nós o usamos extensivamente no Sails e tivemos ótimos resultados nos últimos 2 anos. Ele fornece métodos em ambos paralelo e em série para assíncrono forEach, map, reduce, etc
mikermcneil
25

Hobblin já comentou isso sobre a questão, mas deveria ser uma resposta mesmo!

Usar Function.prototype.bind()é a maneira mais limpa e flexível de fazer isso (com o bônus adicional de poder definir o thiscontexto):

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

Para obter mais informações, consulte estes links 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

dain
fonte
o contexto pode ser passado com o primeiro argumento do bindsetTimeout(postinsql.bind(this, topicId), 4000);
Giuseppe Galano
@GiuseppeGalano totalmente, eu mencionei isso na minha resposta, mas não é necessário para este exemplo :)
dain
Fascinante quanto de brilho sobre aplicativos parciais usando bind. É realmente um código legível.
Sukima
O bind () é suportado apenas no IE9 +, portanto, essa abordagem não funcionará para <IE9 #
615 de Sanjeev
@Sanjeev Use ES5 calço para fazê-lo funcionar no IE mais velhos: github.com/es-shims/es5-shim
Gregers
17

Algumas respostas estão corretas, mas complicadas.

Estou respondendo de novo, quatro anos depois, porque ainda encontro código muito complexo para resolver exatamente essa questão. Existe uma solução elegante.

Antes de tudo, não passe uma string como o primeiro parâmetro ao chamar setTimeout, porque efetivamente chama uma chamada para a lenta função "eval".

Então, como passamos um parâmetro para uma função de tempo limite? Usando o fechamento:

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

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

Alguns sugeriram o uso de função anônima ao chamar a função de tempo limite:

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

A sintaxe funciona. Mas quando settopic é chamado, ou seja, 4 segundos depois, o objeto XHR pode não ser o mesmo. Portanto, é importante pré-vincular as variáveis .

Schien
fonte
1
+1 para uma solução legível, um pouco diferente da minha. Enquanto você tem o setTimeout dentro da função settopic, eu tenho a função fDelayed (your settopic) dentro da função setTimeout.
Dominic
11

Minha resposta:

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

Explicação:

A função anônima criada retorna outra função anônima. Esta função tem acesso ao originalmente transmitido topicId, portanto, não cometerá um erro. A primeira função anônima é chamada imediatamente, passando topicId, para que a função registrada com atraso tenha acesso topicIdno momento da chamada, por meio de fechamentos.

OU

Isso basicamente se converte em:

setTimeout(function() {
  postinsql(topicId); // topicId inside higher scope (passed to returning function)
}, 4000);

EDIT: Eu vi a mesma resposta, então olhe para a dele. Mas não roubei a resposta dele! Eu apenas esqueci de olhar. Leia a explicação e veja se isso ajuda a entender o código.


fonte
Esta é a melhor resposta. Muitas dessas soluções nem sequer respeitam o tempo limite. No entanto, por que você está agrupando a primeira função anônima entre parênteses? Eu não acho que eles são necessários para conseguir isso.
Robert Henderson
esta é a melhor resposta 👍, mas teve que fazer um clone porque quando valores como topicIdsão alterados, o valor no tempo limite também muda. Um clone corrigiu
pariola
10

Substituir

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

com

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

ou melhor ainda, substitua a expressão da string por uma função anônima

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

EDITAR:

O comentário de Brownstone está incorreto, isso funcionará como pretendido, conforme demonstrado ao executá-lo no console do Firebug

(function() {
  function postinsql(id) {
    console.log(id);
  }
  var topicId = 3
  window.setTimeout("postinsql(" + topicId + ")",4000); // outputs 3 after 4 seconds
})();

Observe que estou de acordo com outras pessoas com as quais você deve evitar passar uma string, setTimeoutpois isso chamará eval()a string e passará uma função.

Russ Cam
fonte
Isso não funcionará porque o resultado do postinsql (topicId) será executado pelo setTimeout. Você precisa envolvê-lo em uma função como na primeira resposta, ou usar um auxiliar como .curry () - setTimeout (postinsql.curry (topidId), 4000) do Prototype;
shuckster
2
@ brownstone: Isso está incorreto. A sequência será avaliada quando o tempo limite for disparado.
Miles
9

Você pode passar o parâmetro para a função de retorno de chamada setTimeout como:

setTimeout (função, milissegundos, param1, param2, ...)

por exemplo.

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

function alertMsg(message) {
    alert(message)
}
Jatin Verma
fonte
1
Alguém pode me dizer por que essa resposta não é a preferida? esta é a maneira mais simples na minha opinião! Tão simples quantosetTimeout( (p) => { console.log(p); }, 1000, "hi" );
Mazhar Zandsalimi
1
sim! Essa deve ser a resposta aceita. Do MDN: developer.mozilla.org/pt-BR/docs/Web/API/…
Han
5

Eu sei que faz dez anos desde que essa pergunta foi feita, mas ainda assim, se você rolou até aqui, presumo que você ainda esteja enfrentando algum problema. A solução da Meder Omuraliev é a mais simples e pode ajudar a maioria de nós, mas para aqueles que não querem ter nenhum vínculo, aqui está:

  1. Use Param para setTimeout
setTimeout(function(p){
//p == param1
},3000,param1);
  1. Usar expressão de função chamada imediatamente (IIFE)
let param1 = 'demon';
setTimeout(function(p){
    // p == 'demon'
},2000,(function(){
    return param1;
})()
);
  1. Solução para a questão
function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    setTimeout(postinsql,4000,(function(){
        return xmlhttp.responseText;
    })());
  }
}

function postinsql(topicId)
{
  //alert(topicId);
}
Alpesh Patil
fonte
4

Eu sei que é velho, mas eu queria adicionar meu sabor (preferido) a isso.

Eu acho que uma maneira bem legível de conseguir isso é passar a topicIdpara uma função, que por sua vez usa o argumento para referenciar o ID do tópico internamente. Este valor não será alterado, mesmo que topicIdo exterior seja alterado logo após.

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

ou curto:

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

A resposta de David Meister parece cuidar dos parâmetros que podem mudar imediatamente após a chamada para setTimeout (), mas antes que a função anônima seja chamada. Mas é muito complicado e não muito óbvio. Eu descobri uma maneira elegante de fazer praticamente a mesma coisa usando IIFE (expressão de função imediatamente invicada).

No exemplo abaixo, a currentListvariável é passada para o IIFE, que a salva em seu fechamento, até que a função atrasada seja chamada. Mesmo que a variável currentListmude imediatamente após o código mostrado, setInterval()ela fará a coisa certa.

Sem essa técnica IIFE, a setTimeout()função será definitivamente chamada para cada h2elemento no DOM, mas todas essas chamadas verão apenas o valor de texto do último h2 elemento.

<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>
Gurjeet Singh
fonte
4

Em geral, se você precisar passar uma função como retorno de chamada com parâmetros específicos, poderá usar funções de ordem superior. Isso é bastante elegante com o ES6:

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

setTimeout(someFunction(params), 1000);

Ou se someFunctioné de primeira ordem:

setTimeout(() => someFunction(params), 1000); 
John Hartman
fonte
isso é muito incompatível #
1815996
Elegante de fato! Obrigado
Velojet 13/07/19
3

Observe que o motivo topicId foi "não definido" pela mensagem de erro é que ele existia como uma variável local quando o setTimeout foi executado, mas não quando a chamada atrasada para o postinsql ocorreu. A vida útil variável é especialmente importante para prestar atenção, especialmente ao tentar algo como passar "this" como uma referência de objeto.

Ouvi dizer que você pode passar topicId como um terceiro parâmetro para a função setTimeout. Não são fornecidos muitos detalhes, mas eu tenho informações suficientes para fazê-lo funcionar e é bem-sucedido no Safari. Não sei o que eles significam sobre o "erro de milissegundos". Confira aqui:

http://www.howtocreate.co.uk/tutorials/javascript/timers

Billy
fonte
3

Como resolvi esse estágio?

bem desse jeito :

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

setTimeout espera uma referência a uma função, então eu a criei em um fechamento, que interpreta meus dados e retorna uma função com uma boa instância dos meus dados!

Talvez você possa melhorar esta parte:

_deepFunction(_deepData);

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

Eu testei no chrome, firefox e IE e ele executa bem, não sei sobre desempenho, mas precisava que ele estivesse funcionando.

uma amostra de teste:

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

Talvez você possa alterar a assinatura para torná-la mais compatível:

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)
}

E, finalmente, para responder à pergunta original:

 myNass_setTimeOut( postinsql, 4000, topicId );

Espero que possa ajudar!

ps: desculpe mas inglês não é minha língua materna!

Anonymous0day
fonte
Isso é excessivamente complicado, comparado a outras respostas.
Dan Dascalescu
3

isso funciona em todos os navegadores (o IE é um problema)

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

se você quer passar variável como param vamos tentar isso

se requisito for function e var como parmas, tente isso

setTimeout((param1,param2) => { 
     alert(param1 + param2);
     postinsql(topicId);
},2000,'msg1', 'msg2')

se requisito for apenas variáveis ​​como parâmetros, tente isso

setTimeout((param1,param2) => { alert(param1 + param2) },2000,'msg1', 'msg2')

Você pode tentar isso com ES5 e ES6

homem louco
fonte
2

Você pode tentar a funcionalidade padrão de 'apply ()', algo como isto, pode passar mais número de argumentos conforme sua exigência na matriz

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

setTimeout faz parte do DOM definido pelo WHAT WG.

https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html

O método que você deseja é: -

handle = self.setTimeout( handler [, timeout [, arguments... ] ] )

Agenda um tempo limite para executar o manipulador após milissegundos de tempo limite. Quaisquer argumentos são passados ​​diretamente para o manipulador.

setTimeout(postinsql, 4000, topicId);

Aparentemente, argumentos extras são suportados no IE10. Como alternativa, você pode usar setTimeout(postinsql.bind(null, topicId), 4000);, no entanto, transmitir argumentos extras é mais simples e é preferível.

Fato histórico: nos dias de VBScript, no JScript, o terceiro parâmetro do setTimeout era a linguagem, como uma string, padronizada como "JScript", mas com a opção de usar "VBScript". https://docs.microsoft.com/pt-br/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741500(v%3Dvs.85)

Garrett
fonte
0

@Jiri Vetyska, obrigado pelo post, mas há algo errado no seu exemplo. Eu precisava passar o alvo que está passando o mouse (isto) para uma função de tempo limite e tentei sua abordagem. Testado no IE9 - não funciona. Também fiz algumas pesquisas e parece que, como apontado aqui, o terceiro parâmetro é a linguagem de script que está sendo usada. Nenhuma menção sobre parâmetros adicionais.

Então, segui a resposta do @ meder e resolvi meu problema com este código:

$('.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
}

Espero que isso seja útil para outra pessoa.

Vladislav
fonte
0

Como existe um problema com o terceiro parâmetro optonal no IE e o uso de fechamentos nos impede de alterar as variáveis ​​(em um loop, por exemplo) e ainda alcançar o resultado desejado, sugiro a seguinte solução.

Podemos tentar usar a recursão assim:

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);
}

Precisamos garantir que nada mais mude essas variáveis ​​e que escrevamos uma condição de recursão adequada para evitar recursões infinitas.

Vakhtang Tevdorashvili
fonte
0

// Estas são três respostas muito simples e concisas:

function fun() {
    console.log(this.prop1, this.prop2, this.prop3);
}

let obj = { prop1: 'one', prop2: 'two', prop3: 'three' };

let bound = fun.bind(obj);

setTimeout(bound, 3000);

 // or

function funOut(par1, par2, par3) {

  return function() { 

    console.log(par1, par2, par3);

  }
};

setTimeout(funOut('one', 'two', 'three'), 5000);

 // or

let funny = function(a, b, c) { console.log(a, b, c); };

setTimeout(funny, 2000, 'hello', 'worldly', 'people');
Rico
fonte
0

Respondendo à pergunta, mas com uma simples função de adição com 2 argumentos.

var x = 3, y = 4;

setTimeout(function(arg1, arg2) { 
      delayedSum(arg1, arg2);
}(x, y), 1000);

function delayedSum(param1, param2) {
     alert(param1 + param2); // 7
}
SridharKritha
fonte
0

Você precisa remover aspas da sua setTimeOutchamada de função desta forma:

setTimeout(postinsql(topicId),4000);
Ghanshyam Sharma
fonte
-1

Eu acho que você quer:

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

fonte
1
Corri para casos em que isso simplesmente não funciona (sempre resultando em um erro de 'função não definida'), mas o uso da função anônima funciona. O que é frustrante, pois todos parecem dizer que a sintaxe acima sempre deve funcionar. (será que o jQuery de alguma forma atrapalha o método 'quote as string'?)
DA.
6
Vamos supor que topicId seja uma função ... Ou um objeto. Isso não vai funcionar!
Serafeim 23/11
Se você realmente deseja continuar com esse método, use JSON.stringifypara objetos e matrizes regulares e, em seguida, use JSON.parsedentro da função. No entanto, todo o comportamento será perdido se o objeto tiver métodos.
DarthCadeus
-2

// Estas são três respostas muito simples e concisas:

function fun() {
    console.log(this.prop1, this.prop2, this.prop3);
}

let obj = { prop1: 'one', prop2: 'two', prop3: 'three' };

let bound = fun.bind(obj);

setTimeout(bound, 3000);

 // or

function funOut(par1, par2, par3) {

  return function() { 

    console.log(par1, par2, par3);

  }
};

setTimeout(funOut('one', 'two', 'three'), 5000);

 // or

let funny = function(a, b, c) { console.log(a, b, c); };

setTimeout(funny, 2000, 'hello', 'worldly', 'people');
user11385739
fonte