我如何在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
方法提供了一个在后台调用想要的函数的函数,在async
callback参数中提供了function
return
的唯一参数。 所以在callback函数中,我alert
结果。