Làm cách nào tôi có thể chuyển tham số cho cuộc gọi lại setTimeout ()?


825

Tôi có một số mã JavaScript trông giống như:

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

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

Tôi nhận được một lỗi topicIdkhông được xác định Mọi thứ đã hoạt động trước khi tôi sử dụng setTimeout()chức năng.

Tôi muốn postinsql(topicId)chức năng của tôi được gọi sau một thời gian. Tôi nên làm gì?


75
thật đau lòng khi bình luận về một chủ đề cũ như vậy nhưng tôi chỉ phải cung cấp phiên bản thứ ba (theo ý kiến ​​của tôi thì sạch sẽ hơn nhiều): setTimeout (postinsql.bind (null, topicId), 4000)
Hobblin

14
@Hobblin: tại sao việc lập kỷ lục thẳng? Nó sẽ không làm tổn thương người khác nhiều hơn để đạt được câu hỏi phổ biến này và xem phong cách gọi cũ, bị mất uy tín?
Dan Dascalescu

2
tất cả đều rõ ràng ở đây: w3schools.com/jsref/met_win_settimeout.asp
Vladislav

@dbliss Đề xuất của tôi đã được đề cập trong một số câu trả lời và được thêm vào dưới dạng câu trả lời ở đây: stackoverflow.com/a/15620038/287130 Nhưng tôi rất vui vì đề xuất của tôi được đánh giá cao;)
Hobblin

@Hobblin ah, cảm ơn rất nhiều vì đã chỉ ra điều đó. tôi đã cuộn qua tìm kiếm một câu trả lời được đăng bởi bạn và bỏ lỡ điều đó.
dbliss

Câu trả lời:


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

Bạn cần cung cấp một hàm ẩn danh dưới dạng tham số thay vì chuỗi, phương thức sau thậm chí không nên hoạt động theo đặc tả ECMAScript nhưng các trình duyệt chỉ đơn giản là khoan dung. Đây là giải pháp phù hợp, đừng bao giờ dựa vào việc chuyển một chuỗi dưới dạng 'hàm' khi sử dụng setTimeout()hoặc setInterval(), nó chậm hơn vì nó phải được đánh giá và nó không đúng.

CẬP NHẬT:

Như Hobblin đã nói trong các bình luận của mình cho câu hỏi, bây giờ bạn có thể chuyển các đối số cho hàm bên trong setTimeout bằng cách sử dụng Function.prototype.bind().

Thí dụ:

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

30
window.setTimeoutlà một phương thức DOM và như vậy không được xác định bởi đặc tả ECMAScript. Truyền một chuỗi luôn hoạt động trong các trình duyệt và trên thực tế là một tiêu chuẩn thực tế, khả năng vượt qua một đối tượng chức năng đã được thêm vào sau đó, với JavaScript 1.2, nó rõ ràng là một phần của thông số dự thảo HTML5 ( whatwg.org/specs/web -apps / current-work / bội / / )). Tuy nhiên, sử dụng một chuỗi thay vì một đối tượng hàm thường được coi là kiểu kém vì về cơ bản nó là một dạng bị trì hoãn eval().
Miles

2
var temp = setTimeout (function () {postinsql (topicId);}, 4000); ClearTimeout (tạm thời); ??
Josh Mc

12
Điều gì sẽ xảy ra nếu topicId bị thay đổi sau khi hết thời gian, nhưng trước khi hàm được gọi?
pilau

22
@pilau đó chính xác là vấn đề của tôi: nếu các biến được sử dụng trong hàm ẩn danh thay đổi trước khi hết thời gian (chẳng hạn như trong vòng lặp for) thì nó cũng sẽ thay đổi bên trong hàm. Vì vậy, trong ví dụ của tôi, thiết lập 5 thời gian chờ khác nhau trong một vòng lặp for thực sự đã kết thúc bằng cách sử dụng cùng một biến. Hãy cẩn thận khi sử dụng câu trả lời này!
Cristian

10
@pilau sử dụng một bao đóng khác sẽ giúp topicId = 12; hàm postinsql (topicId) {console.log (topicId); } hàm setTimeOutWithClenses (topicId) {setTimeout (function () {postinsql (topicId);}, 1000)} setTimeOutFunction (topicId); chủ đề = 13;
Halis Yılboğa

727

Trong các trình duyệt hiện đại, "setTimeout" nhận tham số thứ ba được gửi dưới dạng tham số đến chức năng bên trong ở cuối bộ đếm thời gian.

Thí dụ:

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

Thêm chi tiết:


56
Tôi không chắc tại sao câu trả lời này không được chọn là tốt nhất. Sử dụng một hàm ẩn danh hoạt động, chắc chắn, nhưng nếu bạn có thể đơn giản chuyển một tham số thứ ba vào lệnh gọi hàm setTimeout ban đầu ... tại sao không?
Kris Schouw

54
Bởi vì nó không hoạt động trong các phiên bản IE vẫn còn rất nhiều.
Aaron

4
Câu trả lời này thực sự khiến tôi có thể vượt qua một đối tượng sự kiện, các phương pháp khác thì không. Tôi đã có một chức năng ẩn danh.
Glenn Plas

27
Bởi câu trả lời tốt hơn nhiều. Nếu bạn có mã sửa đổi tham số của mình giữa lệnh gọi "setTimeout" và thực thi chức năng ẩn danh - chức năng ẩn danh sẽ nhận được giá trị đã sửa đổi, chứ không phải lúc đó là cuộc gọi setTimeout. ví dụ: for (var i = 0; i <100; i ++) {setTimeout (function () {console.write (i);}, 0); } cái này sẽ ghi "100" 100 lần (đã thử nghiệm trên FF). Câu trả lời hiện tại giúp tránh điều này.
root

1
Theo nhà phát triển.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout, các đối số gọi lại cho Internet Explorer chỉ được hỗ trợ trong các phiên bản> = 10, hãy cẩn thận như trong nhiều trang web tức là8 và eg9 vẫn nhận được một số chia sẻ có liên quan.
le0diaz

154

Sau khi thực hiện một số nghiên cứu và thử nghiệm, việc thực hiện đúng duy nhất là:

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

setTimeout sẽ chuyển tất cả các tham số bổ sung cho chức năng của bạn để chúng có thể được xử lý ở đó.

Hàm ẩn danh có thể hoạt động cho những thứ rất cơ bản, nhưng trong trường hợp của một đối tượng mà bạn phải sử dụng "cái này", không có cách nào để làm cho nó hoạt động. Bất kỳ chức năng ẩn danh nào cũng sẽ thay đổi "cái này" để trỏ đến cửa sổ, do đó bạn sẽ mất tham chiếu đối tượng của mình.


24
Với nỗi buồn trong lòng tôi phải thông báo: điều này không hoạt động trong trình thám hiểm internet. : / Tất cả các thông số phụ đi qua là không xác định.
Amalgovinus

6
Tôi chỉ sử dụngvar that = this; setTimeout( function() { that.foo(); }, 1000);
Ed Williams

2
Điều này là chính xác và được chỉ định trong HTML5. whatwg.org/specs/web-apps/civerse-work/multipage/iêu
Garrett

4
Đây chính xác là câu trả lời giống như của Fabio .
Dan Dascalescu

1
Theo nhà phát triển.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout, các đối số gọi lại cho Internet Explorer chỉ được hỗ trợ trong các phiên bản> = 10, hãy cẩn thận như trong nhiều trang web tức là8 và eg9 vẫn nhận được một số chia sẻ có liên quan.
le0diaz

45

Đây là một câu hỏi rất cũ với câu trả lời đã "đúng" nhưng tôi nghĩ tôi đã đề cập đến một cách tiếp cận khác mà không ai đề cập ở đây. Điều này được sao chép và dán từ thư viện gạch dưới xuất sắc :

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

Bạn có thể chuyển bao nhiêu đối số tùy thích cho hàm được gọi bởi setTimeout như một phần thưởng bổ sung (tốt, thường là phần thưởng), giá trị của các đối số được truyền cho hàm của bạn sẽ bị đóng băng khi bạn gọi setTimeout, vì vậy nếu chúng thay đổi giá trị tại một số điểm giữa khi setTimeout () được gọi và khi hết thời gian, thì ... điều đó không còn quá khó chịu nữa :)

Đây là một câu đố nơi bạn có thể thấy những gì tôi muốn nói.


7
Câu trả lời đó thực sự có hiệu quả nhưng dường như bạn có một số thư viện mà tôi không có. Đây là một sửa chữa nhỏ để nó hoạt động: thay vì lát.call, hãy sử dụng Array.prototype.slice.call (argument, 2)
Melanie

7
@Melanie "một số thư viện"? Tôi đã nói trong câu trả lời rằng đó là thư viện gạch dưới - underscorejs.org . Nhưng vâng, Array.prototype.slice được đặt bí danh để cắt bên trong thư viện đó, vì vậy bạn phải tự làm điều đó nếu bạn không sử dụng nó, điểm tốt :)
David Meister

38

Gần đây tôi đã bắt gặp tình huống duy nhất cần sử dụng setTimeoutmột vòng lặp . Hiểu điều này có thể giúp bạn hiểu làm thế nào để truyền tham số setTimeout.

Phương pháp 1

Sử dụng forEachObject.keys, theo gợi ý của Sukima :

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

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

Tôi đề nghị phương pháp này.

Cách 2

Sử dụng bind:

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

Mã thông báo: http://jsfiddle.net/MsBkW/

Phương pháp 3

Hoặc nếu bạn không thể sử dụng forEachhoặc bind, sử dụng IIFE :

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

Phương pháp 4

Nhưng nếu bạn không quan tâm đến IE <10, thì bạn có thể sử dụng đề xuất của Fabio :

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

Phương pháp 5 (ES6)

Sử dụng một biến phạm vi khối:

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

Mặc dù tôi vẫn sẽ khuyên bạn nên sử dụng Object.keysvới forEachES6.


2
Lưu ý: .bindsẽ không hoạt động cho IE8 trở xuống [ref: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ trộm ]. Tôi đã kết thúc bằng cách sử dụng giải pháp của Schien: stackoverflow.com/a/21213723/1876899
cjspurgeon

1
Nếu bạn trong một môi trường sử dụng bindthì bạn cũng trong một môi trường cung cấp Object.keysforEach. Bạn có thể mất vòng lặp for và có được phạm vi chức năng "miễn phí" (như trong hai con chim với một viên đá không có tài nguyên miễn phí) trong quy trình.
Sukima

@David Sherret trong trường hợp bạn chưa sử dụng nó trước đây, chắc chắn hãy kiểm tra asyncthư viện ( github.com/caolan/async ). Chúng tôi sử dụng nó rộng rãi trong Sails và đã có kết quả tuyệt vời trong 2 năm qua. Nó cung cấp phương pháp trong cả hai song song và trong loạt cho không đồng bộ forEach, map, reducevv
mikermcneil

25

Hobblin đã nhận xét điều này về câu hỏi, nhưng nó thực sự là một câu trả lời!

Sử dụng Function.prototype.bind()là cách sạch nhất và linh hoạt nhất để thực hiện việc này (với phần thưởng được thêm vào là có thể đặt thisbối cảnh):

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

Để biết thêm thông tin, hãy xem các liên kết MDN này:
https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041 https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Feft / liên kết # With_setTimeout


bối cảnh này có thể được thông qua với đối số đầu tiên của ràng buộcsetTimeout(postinsql.bind(this, topicId), 4000);
Giuseppe Galano

@GiuseppeGalano hoàn toàn, tôi đã đề cập rằng trong câu trả lời của tôi, nhưng nó không cần thiết ví dụ này :)
dain

Hấp dẫn có bao nhiêu độ bóng trên các ứng dụng một phần bằng cách sử dụng bind. Nó thực sự làm cho một số mã có thể đọc được.
Sukima

bind () chỉ được hỗ trợ từ IE9 +, vì vậy cách tiếp cận này sẽ không hoạt động cho <IE9
Sanjeev

@Sanjeev Sử dụng shim ES5 để làm cho nó hoạt động trong IE cũ hơn: github.com/es-shims/es5-shim
gregers

17

Một số câu trả lời là đúng nhưng phức tạp.

Tôi đang trả lời điều này một lần nữa, 4 năm sau, bởi vì tôi vẫn chạy vào mã quá phức tạp để giải quyết chính xác câu hỏi này. Có một giải pháp tao nhã.

Trước hết, không chuyển qua một chuỗi làm tham số đầu tiên khi gọi setTimeout vì nó thực sự gọi một cuộc gọi đến hàm "eval" chậm.

Vậy làm thế nào để chúng ta chuyển một tham số cho hàm thời gian chờ? Bằng cách sử dụng đóng cửa:

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

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

Một số đã đề xuất sử dụng chức năng ẩn danh khi gọi chức năng hết thời gian:

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

Cú pháp hoạt động ra. Nhưng theo thời gian giải quyết được gọi, tức là 4 giây sau, đối tượng XHR có thể không giống nhau. Do đó, điều quan trọng là liên kết trước các biến .


1
+1 cho một giải pháp dễ đọc, hơi khác với tôi. Trong khi bạn có setTimeout bên trong chức năng định cư, tôi có chức năng fDelayed (định cư của bạn) bên trong chức năng setTimeout.
Đaminh

11

Câu trả lời của tôi:

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

Giải trình:

Hàm ẩn danh được tạo trả về một hàm ẩn danh khác. Hàm này có quyền truy cập vào thông qua ban đầu topicId, vì vậy nó sẽ không gây ra lỗi. Hàm ẩn danh đầu tiên được gọi ngay lập tức, chuyển vào topicId, do đó, chức năng đã đăng ký có độ trễ có quyền truy cập topicIdtại thời điểm gọi, thông qua các lần đóng.

HOẶC LÀ

Điều này về cơ bản chuyển đổi thành:

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

EDIT: Tôi thấy câu trả lời tương tự, vì vậy hãy nhìn vào anh ấy. Nhưng tôi đã không đánh cắp câu trả lời của anh ấy! Tôi chỉ quên nhìn. Đọc lời giải thích và xem nếu nó giúp để hiểu mã.


Đây là câu trả lời tốt nhất. Nhiều giải pháp trong số này thậm chí sẽ không tôn trọng thời gian chờ. Tuy nhiên, tại sao bạn lại gói hàm ẩn danh đầu tiên trong ngoặc đơn? Tôi không nghĩ rằng họ là cần thiết để thực hiện điều này.
Robert Henderson

đây là câu trả lời tốt nhất, nhưng phải thực hiện một bản sao vì khi các giá trị như topicIdbị thay đổi, giá trị trong thời gian chờ cũng thay đổi. Một bản sao đã sửa nó
pariola

10

Thay thế

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

với

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

hoặc tốt hơn nữa, thay thế biểu thức chuỗi bằng một hàm ẩn danh

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

BIÊN TẬP:

Nhận xét của Brownstone là không chính xác, điều này sẽ hoạt động như dự định, như được thể hiện bằng cách chạy nó trong bảng điều khiển Fireorms

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

Lưu ý rằng tôi đồng ý với những người khác rằng bạn nên tránh truyền một chuỗi setTimeoutvì điều này sẽ gọi eval()trên chuỗi và thay vào đó là truyền một hàm.


Điều này sẽ không hoạt động vì kết quả của postinsql (topicId) sẽ được thực hiện bởi setTimeout. Bạn cần bọc nó trong một hàm như với câu trả lời đầu tiên hoặc sử dụng một trình trợ giúp như Prototype '.curry () - setTimeout (postinsql.curry (topidId), 4000);
shuckster

2
@brownstone: Điều đó không chính xác. Chuỗi sẽ được đánh giá khi hết thời gian chờ.
Miles

9

Bạn có thể chuyển tham số cho hàm gọi lại setTimeout dưới dạng:

setTimeout (hàm, mili giây, param1, param2, ...)

ví dụ.

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

function alertMsg(message) {
    alert(message)
}

1
Bất cứ ai có thể cho tôi biết tại sao câu trả lời này không phải là câu trả lời ưa thích? Đây là cách đơn giản nhất theo ý kiến ​​của tôi! setTimeout( (p) => { console.log(p); }, 1000, "hi" );
Đơn

1
Vâng! Đây phải là câu trả lời được chấp nhận. Từ MDN: developer.mozilla.org/en-US/docs/Web/API/
Han


5

Tôi biết đã 10 năm kể từ khi câu hỏi này được hỏi, nhưng vẫn vậy, nếu bạn đã di chuyển đến đây, tôi cho rằng bạn vẫn phải đối mặt với một số vấn đề. Giải pháp của Meder Omuraliev là giải pháp đơn giản nhất và có thể giúp ích cho hầu hết chúng ta nhưng đối với những người không muốn có bất kỳ ràng buộc nào, thì đây là:

  1. Sử dụng Param cho setTimeout
setTimeout(function(p){
//p == param1
},3000,param1);
  1. Sử dụng Biểu thức hàm được gọi ngay lập tức (IIFE)
let param1 = 'demon';
setTimeout(function(p){
    // p == 'demon'
},2000,(function(){
    return param1;
})()
);
  1. Giải pháp cho câu hỏi
function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    setTimeout(postinsql,4000,(function(){
        return xmlhttp.responseText;
    })());
  }
}

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

4

Tôi biết nó đã cũ nhưng tôi muốn thêm hương vị (ưa thích) của mình vào đây.

Tôi nghĩ rằng một cách khá dễ đọc để đạt được điều này là chuyển hàm topicIdcho một hàm, lần lượt sử dụng đối số để tham chiếu ID chủ đề trong nội bộ. Giá trị này sẽ không thay đổi ngay cả khi topicIdbên ngoài sẽ được thay đổi ngay sau đó.

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

hoặc ngắn:

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

4

Câu trả lời của David Meister dường như quan tâm đến các tham số có thể thay đổi ngay sau cuộc gọi đến setTimeout () nhưng trước khi hàm ẩn danh được gọi. Nhưng nó quá cồng kềnh và không rõ ràng lắm. Tôi phát hiện ra một cách thức thanh lịch để thực hiện khá nhiều điều tương tự bằng cách sử dụng IIFE (biểu thức hàm được gọi ngay lập tức).

Trong ví dụ dưới đây, currentListbiến được chuyển đến IIFE, nó lưu nó trong bao đóng của nó, cho đến khi hàm bị trì hoãn được gọi. Ngay cả khi biến currentListthay đổi ngay sau mã được hiển thị, ý setInterval()chí sẽ làm đúng.

Nếu không có kỹ thuật IIFE này, setTimeout()hàm chắc chắn sẽ được gọi cho từng h2phần tử trong DOM, nhưng tất cả các cuộc gọi đó sẽ chỉ thấy giá trị văn bản của phần tử cuối cùng 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>

4

Nói chung, nếu bạn cần truyền một hàm dưới dạng gọi lại với các tham số cụ thể, bạn có thể sử dụng các hàm bậc cao hơn. Điều này khá thanh lịch với ES6:

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

setTimeout(someFunction(params), 1000);

Hoặc nếu someFunctionlà thứ tự đầu tiên:

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

điều này rất không tương thích
dùng151496

Thanh lịch thật! Cảm ơn
Velojet

3

Lưu ý rằng lý do topicId "không được xác định" cho mỗi thông báo lỗi là vì nó tồn tại dưới dạng biến cục bộ khi setTimeout được thực thi, nhưng không xảy ra khi cuộc gọi bị trì hoãn đến postinsql xảy ra. Tuổi thọ thay đổi đặc biệt quan trọng cần chú ý, đặc biệt là khi thử một cái gì đó như vượt qua "cái này" làm tham chiếu đối tượng.

Tôi nghe nói rằng bạn có thể truyền topicId như một tham số thứ ba cho hàm setTimeout. Không có nhiều chi tiết được đưa ra nhưng tôi đã có đủ thông tin để làm cho nó hoạt động và nó đã thành công trong Safari. Tôi không biết ý nghĩa của chúng về "lỗi mili giây". Kiểm tra nó ở đây:

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


3

Làm thế nào tôi giải quyết giai đoạn này?

chỉ như thế:

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

setTimeout chờ tham chiếu đến một hàm, vì vậy tôi đã tạo nó trong một bao đóng, nó diễn giải dữ liệu của tôi và trả về một hàm với một ví dụ tốt về dữ liệu của tôi!

Có lẽ bạn có thể cải thiện phần này:

_deepFunction(_deepData);

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

Tôi đã thử nghiệm nó trên chrome, firefox và IE và nó hoạt động tốt, tôi không biết về hiệu suất nhưng tôi cần nó để hoạt động.

một bài kiểm tra mẫu:

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

Có lẽ bạn có thể thay đổi chữ ký để làm cho nó phù hợp hơn:

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

Và cuối cùng để trả lời câu hỏi ban đầu:

 myNass_setTimeOut( postinsql, 4000, topicId );

Hy vọng nó có thể giúp!

ps: xin lỗi nhưng tiếng anh không phải tiếng mẹ đẻ của tôi


Điều này là quá phức tạp, so với các câu trả lời khác.
Dan Dascalescu

3

cái này hoạt động trong tất cả các trình duyệt (IE là một trò chơi kỳ quặc)

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

3

Nếu bạn muốn truyền biến như param, hãy thử điều này

nếu yêu cầu là hàm và var như parmas thì hãy thử điều này

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

nếu yêu cầu chỉ là các biến như một tham số thì hãy thử điều này

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

Bạn có thể thử điều này với ES5 và ES6


2

Bạn có thể thử chức năng mặc định của 'áp dụng ()' như thế này, bạn có thể chuyển nhiều số lượng đối số theo yêu cầu của bạn trong mảng

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

1

setTimeout là một phần của DOM được xác định bởi WHAT WG.

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

Phương pháp bạn muốn là: -

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

Lên lịch thời gian chờ để chạy trình xử lý sau khi hết thời gian tính bằng mili giây. Bất kỳ đối số được truyền thẳng đến xử lý.

setTimeout(postinsql, 4000, topicId);

Rõ ràng, các đối số bổ sung được hỗ trợ trong IE10. Ngoài ra, bạn có thể sử dụng setTimeout(postinsql.bind(null, topicId), 4000);, tuy nhiên, việc truyền thêm đối số sẽ đơn giản hơn và điều đó tốt hơn.

Thông tin lịch sử: Trong thời kỳ VBScript, trong JScript, tham số thứ ba của setTimeout là ngôn ngữ, dưới dạng chuỗi, mặc định là "JScript" nhưng với tùy chọn sử dụng "VBScript". https://docs.microsoft.com/en-us/preingly-versions/windows/iNET-explorer/ie-developer/pl platform-apis / aa741500 (v% 3Dvs85)


0

@Jiri Vetyska cảm ơn vì bài đăng, nhưng có một cái gì đó sai trong ví dụ của bạn. Tôi cần phải chuyển mục tiêu được di chuột ra (cái này) cho một chức năng hết thời gian và tôi đã thử cách tiếp cận của bạn. Đã thử nghiệm trong IE9 - không hoạt động. Tôi cũng đã thực hiện một số nghiên cứu và có vẻ như được chỉ ra ở đây , tham số thứ ba là ngôn ngữ script đang được sử dụng. Không đề cập đến các thông số bổ sung.

Vì vậy, tôi đã làm theo câu trả lời của @ meder và giải quyết vấn đề của tôi với mã này:

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

Hy vọng, điều này là hữu ích cho người khác.


0

Vì có một vấn đề với tham số optonal thứ ba trong IE và việc sử dụng các bao đóng ngăn chúng ta thay đổi các biến (ví dụ trong một vòng lặp) và vẫn đạt được kết quả mong muốn, tôi đề xuất giải pháp sau.

Chúng ta có thể thử sử dụng đệ quy như thế này:

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

Chúng ta cần đảm bảo rằng không có gì khác thay đổi các biến này và chúng ta viết một điều kiện đệ quy thích hợp để tránh đệ quy vô hạn.


0

// Đây là ba câu trả lời rất đơn giản và súc tích:

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

0

Trả lời câu hỏi nhưng bằng một hàm bổ sung đơn giản với 2 đối số.

var x = 3, y = 4;

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

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

0

Bạn phải xóa dấu ngoặc kép khỏi setTimeOuthàm gọi như thế này:

setTimeout(postinsql(topicId),4000);

-1

Tôi nghĩ bạn muốn:

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

1
Tôi đã chạy vào các trường hợp đơn giản là nó không hoạt động (luôn dẫn đến lỗi 'hàm không được xác định') nhưng sử dụng hàm ẩn danh sẽ hoạt động. Điều gây nản lòng khi mọi người dường như nói cú pháp trên luôn luôn hoạt động. (có thể là jQuery bằng cách nào đó cản trở phương thức 'trích dẫn dưới dạng chuỗi'?)
DA.

6
Hãy giả sử rằng topicId là một hàm ... Hoặc một đối tượng. Điều này sẽ không làm việc!
Serafeim

Nếu bạn thực sự muốn tiến hành phương pháp này, hãy sử dụng JSON.stringifycho các đối tượng và mảng thông thường, sau đó sử dụng JSON.parsebên trong hàm. Tuy nhiên, tất cả hành vi sẽ bị mất nếu đối tượng có phương thức.
DarthCadeus

-2

// Đây là ba câu trả lời rất đơn giản và súc tích:

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');
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.