首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何制作非阻塞的javascript代码?

如何制作非阻塞的javascript代码?
EN

Stack Overflow用户
提问于 2018-10-11 00:40:03
回答 2查看 0关注 0票数 0

如何进行简单的非块Javascript函数调用?例如:

代码语言:javascript
复制
  //begin the program
  console.log('begin');
  nonBlockingIncrement(10000000);
  console.log('do more stuff'); 

  //define the slow function; this would normally be a server call
  function nonBlockingIncrement(n){
    var i=0;
    while(i<n){
      i++;
    }
    console.log('0 incremented to '+i);
  }

输出

代码语言:javascript
复制
"beginPage" 
"0 incremented to 10000000"
"do more stuff"

如何形成这个简单的循环以异步执行并通过回调函数输出结果?这个想法是不阻止“做更多的东西”:

代码语言:javascript
复制
"beginPage" 
"do more stuff"
"0 incremented to 10000000"

我已经尝试过关于回调和延续的教程,但它们似乎都依赖于外部库或函数。他们都没有在真空中回答这个问题:如何将Javascript代码编写为非阻塞!?

在询问之前,我已经非常努力地寻找这个答案; 请不要以为我没看。我发现的一切都是Node.js特定的([1][2][3][4][5])或其他特定于其他函数或库([6][7][8][9][10][11]),特别是JQuery和setTimeout()。请帮我用Javascript编写非阻塞代码,而不是Javascript和Node等Javascript编写的工具。 请在将其标记为重复之前重新阅读该问题。

EN

回答 2

Stack Overflow用户

发布于 2018-10-11 09:05:15

带回调的SetTimeout是要走的路。但是,要了解您的功能范围与C#或其他多线程环境中的功能范围不同。

Javascript不会等待函数的回调完成。

如果你说:

代码语言:javascript
复制
function doThisThing(theseArgs) {
    setTimeout(function (theseArgs) { doThatOtherThing(theseArgs); }, 1000);
    alert('hello world');
}

在通过的功能之前,警报将会触发

票数 0
EN

Stack Overflow用户

发布于 2018-10-11 09:47:11

不能同时执行两个循环,记住JS是单线程

所以,这样做永远不会奏效

代码语言:javascript
复制
function loopTest() {
    var test = 0
    for (var i; i<=100000000000, i++) {
        test +=1
    }
    return test
}

setTimeout(()=>{
    //This will block everything, so the second won't start until this loop ends
    console.log(loopTest()) 
}, 1)

setTimeout(()=>{
    console.log(loopTest())
}, 1)

如果要实现多线程,则必须使用Web Workers,但它们必须具有单独的js文件,并且只能将对象传递给它们。

但是,通过生成Blob文件设法使用没有分离文件的Web Workers,我也可以传递回调函数。

代码语言:javascript
复制
//A fileless Web Worker
class ChildProcess {
     //@param {any} ags, Any kind of arguments that will be used in the callback, functions too
    constructor(...ags) {
        this.args = ags.map(a => (typeof a == 'function') ? {type:'fn', fn:a.toString()} : a)
    }

    //@param {function} cb, To be executed, the params must be the same number of passed in the constructor 
    async exec(cb) {
        var wk_string = this.worker.toString();
        wk_string = wk_string.substring(wk_string.indexOf('{') + 1, wk_string.lastIndexOf('}'));            
        var wk_link = window.URL.createObjectURL( new Blob([ wk_string ]) );
        var wk = new Worker(wk_link);

        wk.postMessage({ callback: cb.toString(), args: this.args });
 
        var resultado = await new Promise((next, error) => {
            wk.onmessage = e => (e.data && e.data.error) ? error(e.data.error) : next(e.data);
            wk.onerror = e => error(e.message);
        })

        wk.terminate(); window.URL.revokeObjectURL(wk_link);
        return resultado
    }

    worker() {
        onmessage = async function (e) {
            try {                
                var cb = new Function(`return ${e.data.callback}`)();
                var args = e.data.args.map(p => (p.type == 'fn') ? new Function(`return ${p.fn}`)() : p);

                try {
                    var result = await cb.apply(this, args); //If it is a promise or async function
                    return postMessage(result)

                } catch (e) { throw new Error(`CallbackError: ${e}`) }
            } catch (e) { postMessage({error: e.message}) }
        }
    }
}

setInterval(()=>{console.log('Not blocked code ' + Math.random())}, 1000)

console.log("starting blocking synchronous code in Worker")
console.time("\nblocked");

var proc = new ChildProcess(blockCpu, 43434234);

proc.exec(function(block, num) {
    //This will block for 10 sec, but 
    block(10000) //This blockCpu function is defined below
    return `\n\nbla bla ${num}\n` //Captured in the resolved promise
}).then(function (result){
    console.timeEnd("\nblocked")
    console.log("End of blocking code", result)
})
.catch(function(error) { console.log(error) })

//random blocking function
function blockCpu(ms) {
    var now = new Date().getTime();
    var result = 0
    while(true) {
        result += Math.random() * Math.random();
        if (new Date().getTime() > now +ms)
            return;
    }   
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100008897

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档