How can I create an Asynchronous function in Javas

2019-01-01 01:41发布

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

As you can see in the console, the "animate" function is asynchronous, and it "fork"s the flow of the event handler block code. In fact :

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

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

follow the flow of the block code!

If I wish to create my function asyncFunct() { } with this behaviour, how can I do it with javascript/jquery? I think there is a strategy without the use of setTimeout()

12条回答
与君花间醉酒
2楼-- · 2019-01-01 02:15

here you have simple solution (other write about it) http://www.benlesh.com/2012/05/calling-javascript-function.html

And here you have above ready solution:

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

TEST 1 (may output '1 x 2 3' or '1 2 x 3' or '1 2 3 x'):

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

TEST 2 (will always output 'x 1'):

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

This function is executed with timeout 0 - it will simulate asynchronous task

查看更多
不再属于我。
3楼-- · 2019-01-01 02:18

MDN has a good example on the use of setTimeout preserving "this".

Like the following:

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

$(".someSelector").each(function() {
    setTimeout(doSomething.bind(this), 0);
});
查看更多
看风景的人
4楼-- · 2019-01-01 02:21

Edit: I totally misunderstood the question. In the browser, I would use setTimeout. If it was important that it ran in another thread, I would use Web Workers.

查看更多
其实,你不懂
5楼-- · 2019-01-01 02:23

If you want to use Parameters and regulate the maximum number of async functions you can use a simple async worker I've build:

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

You can use it like this:

var myFunction = function() {
 ...
}
var myFunctionB = function() {
 ...
}
var myParams = { name: "John" };

var bgworker = new BackgroundWorker();
bgworker.runTask(myFunction, 0, myParams);
bgworker.runTask(myFunctionB, 0, null);
查看更多
忆尘夕之涩
6楼-- · 2019-01-01 02:25

Unfortunately, JavaScript doesn't provide an async functionality. It works only in a single one thread. But the most of the modern browsers provide Workers, that are second scripts which gets executed in background and can return a result. So, I reached a solution I think it's useful to asynchronously run a function, which creates a worker for each async call.

The code below contains the function async to call in background.

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

This is an example for usage:

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

This executes a function which iterate a for with a huge number to take time as demonstration of asynchronicity, and then gets the double of the passed number. The async method provides a function which calls the wanted function in background, and in that which is provided as parameter of async callbacks the return in its unique parameter. So in the callback function I alert the result.

查看更多
有味是清欢
7楼-- · 2019-01-01 02:31

This page walks you through the basics of creating an async javascript function.

Performing asynchronous function calls in JavaScript using arguments normally involves constructing the expression argument to setTimeout or setInterval manually.

If that doesn't solve it for you, check out the documentation on the animate function.

查看更多
登录 后发表回答