如何在Javascript中创建异步函数?

mar*_*zzz 136 javascript jquery asynchronous function

看看这段代码:

<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");    
});
Run Code Online (Sandbox Code Playgroud)

正如您在控制台中看到的那样,"animate"函数是异步的,它"分叉"事件处理程序块代码的流程.事实上 :

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

function asyncFunct() {
    console.log("finished");
}
Run Code Online (Sandbox Code Playgroud)

按照块代码的流程!

如果我想创建我function asyncFunct() { }的这种行为,我怎么能用javascript/jquery做到这一点?我认为这是不使用的策略 setTimeout()

pim*_*vdb 177

你不能做一个真正的自定义异步功能.您最终必须利用本机提供的技术,例如:

  • setInterval
  • setTimeout
  • requestAnimationFrame
  • XMLHttpRequest
  • WebSocket
  • Worker
  • 一些HTML5 API,例如File API,Web Database API
  • 支持的技术 onload
  • ... 很多其他的

实际上,对于动画jQuery 使用 setInterval.

  • @MatheusFelipe https://youtu.be/8aGhZQkoFbQ到目前为止关于这个话题的最佳话题... (9认同)
  • 我昨天和朋友讨论过这个问题,所以这个答案很完美!我理解并能够识别异步函数并在 JS 中正确使用它们。但我不清楚“为什么”我们不能实现自定义的。它就像一个黑匣子,我们知道如何使其工作(例如使用“setInterval”),但我们甚至无法打开它来查看它是如何完成的。您是否有关于该主题的更多信息? (3认同)
  • @MatheusFelipe这些函数是javascript引擎实现的原生函数,唯一可以依赖的是规范,[例如HTML5计时器](http://www.w3.org/TR/2011/WD-html5-20110525/timers .html)并且信任他们根据规格行事的黑匣子性质. (2认同)
  • 那么“承诺”呢?它是否给出了“awaitable”? (2认同)

Šim*_*das 66

你可以使用一个计时器:

setTimeout( yourFn, 0 );
Run Code Online (Sandbox Code Playgroud)

(哪里yourFn是你的功能的参考)

或者,与Lodash:

_.defer( yourFn );
Run Code Online (Sandbox Code Playgroud)

延迟调用func直到当前调用堆栈已清除.func在调用它时提供任何其他参数.

  • 这不起作用,我在画布中绘制的javascript函数使UI始终无响应。 (3认同)
  • @ gab06 - 我说你的画布绘图功能因其自身的原因而受阻.将其动作拆分为许多较小的动作并使用计时器调用它们中的每一个:您将看到这种界面对您的鼠标点击响应等. (2认同)

fid*_*der 29

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

在这里你有以上的解决方案:

function async(your_function, callback) {
    setTimeout(function() {
        your_function();
        if (callback) {callback();}
    }, 0);
}
Run Code Online (Sandbox Code Playgroud)

测试1(可输出'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);
Run Code Online (Sandbox Code Playgroud)

测试2(将始终输出'x 1'):

async(function() {console.log('x');}, function() {console.log(1);});
Run Code Online (Sandbox Code Playgroud)

该函数在超时0时执行 - 它将模拟异步任务

  • TEST 1实际上只能输出'1 2 3 x',TEST 2保证每次输出'1 x'.在TEST 2中出现意外结果的原因是因为`console.log(1)`被调用而输出(`undefined`)被作为第二个参数传递给`async()`.在TEST 1的情况下,我认为你并不完全理解JavaScript的执行队列.因为对`console.log()`的每次调用都发生在同一个堆栈中,所以保证最后记录`x`.我对这个错误信息的答案进行了投票,但没有足够的代表. (6认同)

Eth*_*gue 10

这是一个函数,它接受另一个函数并输出一个运行异步的版本.

var async = function (func) {
  return function () {
    var args = arguments;
    setTimeout(function () {
      func.apply(this, args);
    }, 0);
  };
};
Run Code Online (Sandbox Code Playgroud)

它用作创建异步函数的简单方法:

var anyncFunction = async(function (callback) {
    doSomething();
    callback();
});
Run Code Online (Sandbox Code Playgroud)

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


Lin*_*iel 5

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


sha*_*bus 5

本页面将向您介绍创建异步javascript函数的基础知识.

使用参数在JavaScript中执行异步函数调用通常涉及手动将表达式参数构造为setTimeout或setInterval.

如果这不能解决问题,请查看该__CODE__功能的文档.


hd8*_*335 5

promises最近,但是为了展示在ES6中引入后使用的简单解决方案,它处理异步调用要容易得多

您以新的承诺设置了异步代码:

var asyncFunct = new Promise(function(resolve, reject) {
    $('#link').animate({ width: 200 }, 2000, function() {
        console.log("finished");                
        resolve();
    });             
});
Run Code Online (Sandbox Code Playgroud)

请注意resolve()在异步调用结束时进行设置。
然后.then(),在promise中添加要在异步调用完成后运行的代码:

asyncFunct.then((result) => {
    console.log("Exit");    
});
Run Code Online (Sandbox Code Playgroud)

这是它的一个片段:

var asyncFunct = new Promise(function(resolve, reject) {
    $('#link').animate({ width: 200 }, 2000, function() {
        console.log("finished");                
        resolve();
    });             
});
Run Code Online (Sandbox Code Playgroud)
asyncFunct.then((result) => {
    console.log("Exit");    
});
Run Code Online (Sandbox Code Playgroud)

JSFiddle