153 votes

Comment créer une fonction asynchrone en Javascript ?

Regarde ça code :

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

Comme vous pouvez le voir dans la console, la fonction "animate" est asynchrone, et elle "bifurque" le flux de code du bloc du gestionnaire d'événement. En effet :

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

function asyncFunct() {
    console.log("finished");
}

suivez le flux du code-bloc !

Si je souhaite créer mon function asyncFunct() { } avec ce comportement, comment puis-je le faire avec javascript/jquery ? Je pense qu'il existe une stratégie sans l'utilisation de setTimeout()

0 votes

Jetez un coup d'œil aux sources de jQuery :)

0 votes

Le mathod .animate() utilise un callback. Animate appellera la callback lorsque l'animation sera terminée. Si vous souhaitez obtenir le même comportement que .animate(), vous avez besoin d'un callback (appelé par la fonction "main" après d'autres opérations). C'est différent si vous avez besoin d'une fonction asynchrone "complète" (une fonction appelée sans bloquer le flux d'exécution). Dans ce cas, vous pouvez utiliser setTimeout() avec un délai proche de 0.

0 votes

@Fabio Buda : pourquoi callback() devrait implémenter une sorte d'asynchrone ? En fait, ce n'est pas le cas jsfiddle.net/5H9XT/9

1voto

Davide Cannizzo Points 964

Malheureusement, JavaScript ne fournit pas de fonctionnalité asynchrone. Il ne fonctionne que dans un seul thread. Mais la plupart des navigateurs modernes fournissent Worker s qui sont des seconds scripts qui s'exécutent en arrière-plan et peuvent retourner un résultat. Donc, j'ai trouvé une solution Je pense qu'il est utile d'exécuter de manière asynchrone une fonction, qui crée un travailleur pour chaque appel asynchrone.

Le code ci-dessous contient la fonction async pour appeler en arrière-plan.

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

Il s'agit d'un exemple d'utilisation :

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

Ceci exécute une fonction qui itère une for avec un nombre énorme pour prendre du temps comme démonstration de l'asynchronisme, et reçoit ensuite le double du nombre passé. Le site async fournit un function qui appelle la fonction recherchée en arrière-plan, et dans celle qui est fournie comme paramètre de la fonction async les rappels de la return dans son paramètre unique. Ainsi, dans la fonction de rappel, je alert le résultat.

0voto

xtian Points 161

MDN dispose d'un bon exemple sur l'utilisation de setTimeout préservant "this".

Comme les suivantes :

function doSomething() {
    // use 'this' to handle the selected element here
}

$(".someSelector").each(function() {
    setTimeout(doSomething.bind(this), 0);
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X