如何进行简单的非块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);
}
输出
"beginPage"
"0 incremented to 10000000"
"do more stuff"
如何形成这个简单的循环以异步执行并通过回调函数输出结果?这个想法是不阻止“做更多的东西”:
"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编写的工具。 请在将其标记为重复之前重新阅读该问题。
发布于 2018-10-11 09:05:15
带回调的SetTimeout是要走的路。但是,要了解您的功能范围与C#或其他多线程环境中的功能范围不同。
Javascript不会等待函数的回调完成。
如果你说:
function doThisThing(theseArgs) {
setTimeout(function (theseArgs) { doThatOtherThing(theseArgs); }, 1000);
alert('hello world');
}
在通过的功能之前,警报将会触发
发布于 2018-10-11 09:47:11
不能同时执行两个循环,记住JS是单线程
所以,这样做永远不会奏效
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,我也可以传递回调函数。
//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;
}
}
https://stackoverflow.com/questions/-100008897
复制相似问题