使用生成器暂停直到承诺解决
Using generators to pause until promise resolves
我在 node.js 中有一个批处理作业: 将文件复制到目录中,对文件进行分析,然后删除文件。
我想遍历一组作业并使用生成器暂停执行,直到该批处理作业完成,然后再开始另一个作业。这是我目前所拥有的:
const cars = ["toyota", "honda", "acura"];
function copyFilesAndRunAnalysis(car) {
return new Promise(function(resolve, reject) {
setTimeout(function() { // simulate some delay
resolve(); // control should return to generator here
}, 1000);
});
}
function* doCar(car) {
yield copyFilesAndRunAnalysis(car);
}
// BEGIN HERE
console.log('start here');
carBatch = doCar(cars[0]);
carBatch.next(); // confusion here!!!
carBatch.next(); // should this all be in a forEach loop?
我想做的是让 forEach 遍历每辆车,在 copyFilesAndRunAnalysis
方法中完成所有相应的工作——暂停直到 Promise.resolve()
,然后继续下一个一。尝试 forEach 根本没有任何结果 运行。
ES6 生成器与异步执行没有任何关系。它们提供了在第三方代码中实现异步控制流的可用机制(特别是 co
)。
可以这么用
co(function* () {
console.log('start here');
for (let car of cars) {
yield copyFilesAndRunAnalysis(car);
}
console.log('end here');
});
co
将包装的生成器函数转换为承诺,并且不会创造奇迹。所有异步操作都应在生成器函数内执行。
您在 js
的提问中没有使用 .value
。 Generator
生成的 next()
对象的 .value
将是从 copyFilesAndRunAnalysis
返回的 Promise
,其中 .then()
可以链接到 .next().value()
, Array.prototype.shift()
可用于递归调用 doCar
直到没有项目保留在 cars
数组的原始或副本中。
const cars = ["toyota", "honda", "acura"];
let carsCopy = cars.slice(0);
function copyFilesAndRunAnalysis(car) {
return new Promise(function(resolve, reject) {
setTimeout(function() { // simulate some delay
resolve(car); // control should return to generator here
}, 1000);
})
}
function* doCar(cars) {
yield copyFilesAndRunAnalysis(cars);
}
// BEGIN HERE
console.log("start here");
carBatch = doCar(carsCopy.shift());
carBatch.next().value.then(function re(data) {
console.log(data);
return carsCopy.length
? doCar(carsCopy.shift()).next().value.then(re)
: "complete"
})
.then(function(complete) {
console.log(complete);
})
注意,使用Promise
递归可以实现相同的过程;不使用 Generator
函数。
const cars = ["toyota", "honda", "acura"];
let carsCopy = cars.slice(0);
function copyFilesAndRunAnalysis(car) {
return new Promise(function(resolve, reject) {
setTimeout(function() { // simulate some delay
resolve(car); // control should return to generator here
}, 1000);
})
}
// BEGIN HERE
console.log("start here");
carBatch = copyFilesAndRunAnalysis(carsCopy.shift());
carBatch.then(function re(data) {
console.log(data);
return carsCopy.length
? copyFilesAndRunAnalysis(carsCopy.shift()).then(re)
: "complete"
})
// do stuff when all items within `cars` have been
// processed through `copyFilesAndRunAnalysis`
.then(function(complete) {
console.log(complete);
})
我在 node.js 中有一个批处理作业: 将文件复制到目录中,对文件进行分析,然后删除文件。
我想遍历一组作业并使用生成器暂停执行,直到该批处理作业完成,然后再开始另一个作业。这是我目前所拥有的:
const cars = ["toyota", "honda", "acura"];
function copyFilesAndRunAnalysis(car) {
return new Promise(function(resolve, reject) {
setTimeout(function() { // simulate some delay
resolve(); // control should return to generator here
}, 1000);
});
}
function* doCar(car) {
yield copyFilesAndRunAnalysis(car);
}
// BEGIN HERE
console.log('start here');
carBatch = doCar(cars[0]);
carBatch.next(); // confusion here!!!
carBatch.next(); // should this all be in a forEach loop?
我想做的是让 forEach 遍历每辆车,在 copyFilesAndRunAnalysis
方法中完成所有相应的工作——暂停直到 Promise.resolve()
,然后继续下一个一。尝试 forEach 根本没有任何结果 运行。
ES6 生成器与异步执行没有任何关系。它们提供了在第三方代码中实现异步控制流的可用机制(特别是 co
)。
可以这么用
co(function* () {
console.log('start here');
for (let car of cars) {
yield copyFilesAndRunAnalysis(car);
}
console.log('end here');
});
co
将包装的生成器函数转换为承诺,并且不会创造奇迹。所有异步操作都应在生成器函数内执行。
您在 js
的提问中没有使用 .value
。 Generator
生成的 next()
对象的 .value
将是从 copyFilesAndRunAnalysis
返回的 Promise
,其中 .then()
可以链接到 .next().value()
, Array.prototype.shift()
可用于递归调用 doCar
直到没有项目保留在 cars
数组的原始或副本中。
const cars = ["toyota", "honda", "acura"];
let carsCopy = cars.slice(0);
function copyFilesAndRunAnalysis(car) {
return new Promise(function(resolve, reject) {
setTimeout(function() { // simulate some delay
resolve(car); // control should return to generator here
}, 1000);
})
}
function* doCar(cars) {
yield copyFilesAndRunAnalysis(cars);
}
// BEGIN HERE
console.log("start here");
carBatch = doCar(carsCopy.shift());
carBatch.next().value.then(function re(data) {
console.log(data);
return carsCopy.length
? doCar(carsCopy.shift()).next().value.then(re)
: "complete"
})
.then(function(complete) {
console.log(complete);
})
注意,使用Promise
递归可以实现相同的过程;不使用 Generator
函数。
const cars = ["toyota", "honda", "acura"];
let carsCopy = cars.slice(0);
function copyFilesAndRunAnalysis(car) {
return new Promise(function(resolve, reject) {
setTimeout(function() { // simulate some delay
resolve(car); // control should return to generator here
}, 1000);
})
}
// BEGIN HERE
console.log("start here");
carBatch = copyFilesAndRunAnalysis(carsCopy.shift());
carBatch.then(function re(data) {
console.log(data);
return carsCopy.length
? copyFilesAndRunAnalysis(carsCopy.shift()).then(re)
: "complete"
})
// do stuff when all items within `cars` have been
// processed through `copyFilesAndRunAnalysis`
.then(function(complete) {
console.log(complete);
})