我需要按顺序调用某些函数,并且为了强制框架在每一步之后执行脏检查,我使用setTimeout(func,0)来触发脏检查机制。
我知道简单地逐个调用setTimeout并不能保证传递的异步函数会按预期顺序调用,因此我克服了以下解决方案:
function foo(arg){
setTimeout(()=>console.log('executing task' + arg),0);
console.log('on call stack' + arg);
return foo;
}
我试过foo(1)(2)(3)(4)(5)
,它运行正常。但我不确定它是否会始终正常工作。
任何人都可以帮助我!
@Steffomio的答案绝对可以使排队的任务具有确定性,它还可以确保每个任务都有自己的事件循环。
这是我的改编版本:
function queueTask(task) {
var queue = [];
function nextTask() {
setTimeout(function () {
queue.length && queue.shift()(); taskCount++;
queue.length && nextTask();
}, 0);
}
return (function pushTask(task) {
queue.push(task);
//After the first call trigger the timeout asynchrony
if (queue.length === 1) { nextTask(); }
return pushTask;
})(task);
}
//Test part below
function t(arg) { return function () { console.log('Task ' + arg); } }
var taskCount = 0;
var beginTime = Date.now();
queueTask(t(1))(t(2))(t(3))(t(4))(t(5))
(t('a'))(t('b'))(t('c'))(t('d'))(t('e'))
(t(1))(t(2))(t(3))(t(4))(t(5))
(t('a'))(t('b'))(t('c'))(t('d'))(t('e'))
(function () { console.log(taskCount + ' tasks executed, Time elapsed: ' + (Date.now() - beginTime)); });
经过一些研究后,我了解到传递给setTimeout
的回调只有在清除了调用堆栈时才会被系统调用(不再有代码),因此排队任务的实际执行将无法启动直到排队完成,并且如果我们线性地排队几个0延迟超时任务,当下一个事件循环开始时,它们将全部在一次运行中执行。那不是我想要的!因此,在前面setTimeout
的回调中调用setTimeout
是迄今为止我知道的唯一方法来强制执行滴答任务调度。
为了更好地理解,请参阅Philip Roberts在JSConf EU 2014上发表的演讲"What the heck is the event loop anyway"
答案 0 :(得分:2)
可能这种方法适合你
function foo(args) {
return new Promise((resolve, reject) => {
// your code based on args
if (args.length) {
console.log("processing", args[0]);
resolve(args.slice(1, args.length));
} else {
reject("finished");
}
}).then(args => {
return foo(args);
}).catch(() => {
console.log("Tasks completed...");
});
}
foo([1, 2, 3 ,4, 5]);
输出应该是这样的:
processing 1
processing 2
processing 3
processing 4
processing 5
Tasks completed...
答案 1 :(得分:1)
你需要一个队列:
//CREATOR OBJECT
using UnityEngine;
using System.Collections;
public class createProjectile : MonoBehaviour
{
public GameObject projectile;
void OnMouseDown()
{
Instantiate(projectile);
}
}
用于测试复制和粘贴代码到控制台。