使用生成器暂停直到promise结算

时间:2016-05-21 18:51:19

标签: javascript node.js ecmascript-6 generator es6-promise

我在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()然后再到下一个。{1}}。尝试forEach根本不会运行任何东西。

2 个答案:

答案 0 :(得分:3)

您在问题.value处不使用js。由.value产生的next()对象的Generator将是从Promise返回的copyFilesAndRunAnalysis,其中.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); 
})

答案 1 :(得分:1)

ES6生成器与异步执行没有任何关系。它们提供了在第三方代码中实现异步控制流的可用机制(特别是co)。

可以像那样使用

co(function* () {
    console.log('start here');

    for (let car of cars) {
        yield copyFilesAndRunAnalysis(car);
    }

    console.log('end here');
});

co将包裹的生成器函数转换为承诺并且不会创造奇迹。所有异步操作都应该在生成器函数内执行。