我想以块的形式运行一个函数,所以它会等待10k的promises来解析然后继续,我使用下面的生成器函数:
function* processNodes(nodes, task){
let i;
let cnt = 0;
let promiseArray = new Array(10000);
let pInd = 0;
let currId;
for(i = 0; i<nodes.length; i++){
currId = nodes[i];
promiseArray[pInd++] = asyncFunc(currId, 0, task); // return a promise
cnt++;
if(cnt > 10000){
console.log("going to yield", promiseArray)
let pall = Promise.all(promiseArray);
console.log("promise all", pall);
yield pall;
console.log("return from yield"); // never get here
pInd = cnt = 0;
}
}
}
但即使我看到pall
已经解决,它也永远不会从收益中回归。
是否可以使用生成器功能执行此类操作?
编辑: 我想我要做的是实现像Bluebird的协程一样:http://bluebirdjs.com/docs/api/promise.coroutine.html
Edit2:这是我调用此函数的方式:
let x = processNodes(allNodes, someSimpleTask);
x.next();
答案 0 :(得分:2)
您的问题是您不应该使用生成器功能。您永远不会到达console.log('return from field')
,因为在yield
处,代码在yield语句之后停止执行。只有当你再次调用迭代器时,它才会在yield语句之后继续(直到下一个yield语句)
因此,生成器创建一个迭代器,它具有value
和bool标志done
。只要完成没有设置为true,您就可以/应该再次调用下一个函数
您的代码的简化版本可以是以下
// a very basic async function, just outputting the argument each 5 ms
function asyncFunc(arg) {
return new Promise(function(resolve) {
setTimeout(() => {
console.log(arg);
resolve();
}, 5);
});
}
// the generator
function* generator(processNodes, task) {
var limit = 4,
queue = [];
for (let i = 0; i < processNodes.length; i++) {
queue.push(task(processNodes[i]));
if (queue.length >= limit) {
yield Promise.all(queue);
// clears the queue after pushing
console.log('after queue');
queue = [];
}
}
// make sure the receiver gets the full queue :)
if (queue.length !== 0) {
yield Promise.all(queue);
}
}
function runThroughArguments(args, task) {
return new Promise(function(resolve) {
setTimeout(() => {
var nodes = generator(args, task),
iterator = nodes.next();
if (!iterator.done) {
// if it's not done, we have to recall the functionallity
iterator.value.then(function q() {
setTimeout(() => {
iterator = nodes.next();
if (!iterator.done && iterator.value) {
// call the named function (in this case called q) which is this function after the promise.all([]) completed
iterator.value.then(q);
} else {
// everything finished and all promises are through
resolve();
}
}, 2);
});
} else {
iterator.value.then(resolve);
}
}, 2);
});
}
runThroughArguments(
['hey', 'you', 'the', 'rock', 'steady', 'crew'],
asyncFunc).then(() => console.log('completed'));
console.log('runs before everything');
在上面的代码片段中,它也会通过一个承诺。因此,当完整队列通过时,您可以得到通知,它比原始代码段复杂一点here
可以在MDN
上找到您正在使用的模式的更易于理解的解释