我如何在Javascript中创build一个asynchronous函数?

我的意思是,看看这个代码 :

<a href="#" id="link">Link</a> <span>Moving</span> $('#link').click(function () { console.log("Enter"); $('#link').animate({ width: 200 }, 2000, function() { console.log("finished"); }); console.log("Exit"); }); 

正如你在控制台中看到的那样,“animate”函数是asynchronous的,它“分叉”事件处理程序块代码的stream程。 事实上 :

 $('#link').click(function () { console.log("Enter"); asyncFunct(); console.log("Exit"); }); function asyncFunct() { console.log("finished"); } 

按照代码的stream程!

如果我想创build我的function asyncFunct() { }与此行为,我怎么能做到这一点与JavaScript / jQuery的? 我认为有没有使用setTimeout()的策略

你不能做一个真正的自定义asynchronous函数。 您最终必须利用本地提供的技术,例如:

  • setInterval
  • setTimeout
  • requestAnimationFrame
  • XMLHttpRequest
  • WebSocket
  • Worker
  • 一些HTML5 API,如File API,Web数据库API
  • 支持onload技术
  • … 好多其它的

实际上,对于animationjQuery 使用 setInterval

你可以使用一个计时器:

 setTimeout( yourFn, 0 ); 

(其中yourFn是对你的函数的引用)

或者用underscore.js :

 _.defer( yourFn ); 

延迟调用函数,直到当前调用堆栈已经清除,类似于使用延迟为0的setTimeout。用于在块中执行昂贵的计算或HTML呈现,而不阻止UI线程更新。

在这里你有简单的解决scheme(其他写关于它) http://www.benlesh.com/2012/05/calling-javascript-function.html

在这里,你有以上的解决scheme:

 function async(your_function, callback) { setTimeout(function() { your_function(); if (callback) {callback();} }, 0); } 

testing1( 可输出'1 x 2 3'或'1 2 x 3'或'1 2 3 x' ):

 console.log(1); async(function() {console.log('x')}, null); console.log(2); console.log(3); 

testing2( 将始终输出'x 1' ):

 async(function() {console.log('x');}, function() {console.log(1);}); 

这个函数执行时间为0 – 它将模拟asynchronous任务

这是一个函数,它接受另一个函数并输出一个运行asynchronous的版本。

 var async = function (func) { return function () { var args = arguments; setTimeout(function () { func.apply(this, args); }, 0); }; }; 

它被用作一个简单的方法来做一个asynchronous函数:

 var anyncFunction = async(function (callback) { doSomething(); callback(); }); 

这与@ fider的答案不同,因为函数本身具有自己的结构(没有添加callback,它已经在函数中),也因为它创build了一个可以使用的新函数。

本页面将引导您完成创buildasynchronousJavaScriptfunction的基础知识。

使用参数在JavaScript中执行asynchronous函数调用通常涉及手动构buildsetTimeout或setInterval的expression式参数。

如果这不能解决你的问题,请查看关于animate函数的文档。

编辑:我完全误解了这个问题。 在浏览器中,我会使用setTimeout 。 如果它在另一个线程中运行很重要,我会使用Web Workers 。

如果你想使用参数,并规定了最大数量的asynchronous函数,你可以使用我build立的一个简单的asynchronous工作:

 var BackgroundWorker = function(maxTasks) { this.maxTasks = maxTasks || 100; this.runningTasks = 0; this.taskQueue = []; }; /* runs an async task */ BackgroundWorker.prototype.runTask = function(task, delay, params) { var self = this; if(self.runningTasks >= self.maxTasks) { self.taskQueue.push({ task: task, delay: delay, params: params}); } else { self.runningTasks += 1; var runnable = function(params) { try { task(params); } catch(err) { console.log(err); } self.taskCompleted(); } // this approach uses current standards: setTimeout(runnable, delay, params); } } BackgroundWorker.prototype.taskCompleted = function() { this.runningTasks -= 1; // are any tasks waiting in queue? if(this.taskQueue.length > 0) { // it seems so! let's run it x) var taskInfo = this.taskQueue.splice(0, 1)[0]; this.runTask(taskInfo.task, taskInfo.delay, taskInfo.params); } } 

你可以像这样使用它:

 var myFunction = function() { ... } var myFunctionB = function() { ... } var myParams = { name: "John" }; var bgworker = new BackgroundWorker(); bgworker.runTask(myFunction, 0, myParams); bgworker.runTask(myFunctionB, 0, null); 

我在这里看到,没有人谈到诺言。 所以我build议你了解诺言: 看看这个链接

 Function.prototype.applyAsync = function(params, cb){ var function_context = this; setTimeout(function(){ var val = function_context.apply(undefined, params); if(cb) cb(val); }, 0); } // usage var double = function(n){return 2*n;}; var display = function(){console.log(arguments); return undefined;}; double.applyAsync([3], display); 

虽然与其他解决scheme没有根本的不同,但我认为我的解决scheme还有一些额外的好处:

  • 它允许参数的function
  • 它将函数的输出传递给callback函数
  • 它被添加到Function.prototype允许更好的方式来调用它

此外,与内置函数Function.prototype.apply的相似性似乎适合我。

MDN有一个使用setTimeout保存“this”的好例子 。

如下所示:

 function doSomething() { // use 'this' to handle the selected element here } $(".someSelector").each(function() { setTimeout(doSomething.bind(this), 0); }); 

在@pimvdb的最佳答案旁边,以防万一你想知道, async.js也不提供真正的asynchronous函数。 这是一个(非常)精简版的图书馆的主要方法:

 function asyncify(func) { // signature: func(array) return function (array, callback) { var result; try { result = func.apply(this, array); } catch (e) { return callback(e); } /* code ommited in case func returns a promise */ callback(null, result); }; } 

所以这个函数可以防止错误并且把它交给callback来处理,但是代码和其他JS函数一样同步。

不幸的是,JavaScript不提供asynchronousfunction。 它只能在一个单一的线程中工作。 但是大多数现代浏览器都提供了Worker ,它们是在后台执行的第二个脚本,可以返回结果。 所以,我达成了一个解决scheme,我认为这是非常有用的asynchronous运行一个函数,为每个asynchronous调用创build一个工人。

下面的代码包含 在后台调用的 async 函数

 Function.prototype.async = function(callback) { let blob = new Blob([ "self.addEventListener('message', function(e) { self.postMessage({ result: (" + this + ").apply(null, e.data) }); }, false);" ], { type: "text/javascript" }); let worker = new Worker(window.URL.createObjectURL(blob)); worker.addEventListener("message", function(e) { this(e.data.result); }.bind(callback), false); return function() { this.postMessage(Array.from(arguments)); }.bind(worker); }; 

这是一个使用的例子:

 (function(x) { for (let i = 0; i < 999999999; i++) {} return x * 2; }).async(function(result) { alert(result); })(10); 

这个函数执行一个迭代一个巨大数字的函数来花费时间来演示asynchronous性,然后获得传递数字的两倍。 async方法提供了一个在后台调用想要的函数的函数,在asynccallback参数中提供了function return的唯一参数。 所以在callback函数中,我alert结果。