最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using generators to pause until promise resolves - Stack Overflow

programmeradmin5浏览0评论

I have a batch job in node.js that: copies files into a directory, does analysis on files, then removes files.

I would like to iterate over an array of jobs and use generators to pause execution until that batch job is plete before starting another job. Here is what I have so far:

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?

I have a batch job in node.js that: copies files into a directory, does analysis on files, then removes files.

I would like to iterate over an array of jobs and use generators to pause execution until that batch job is plete before starting another job. Here is what I have so far:

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?

What I'd like to do is have a forEach that loops over each car, does all the respective work in the copyFilesAndRunAnalysis method -- pausing until Promise.resolve() and then on to the next one. Trying forEach does not make anything run at all.

Share Improve this question edited May 23, 2016 at 23:43 Jeff asked May 21, 2016 at 18:51 JeffJeff 2,4435 gold badges28 silver badges46 bronze badges 4
  • Not sure that you can use generators to do this. Generators are not designed for handling async operations. What you want do to is covered in the idea of observables. Observables are now in ES7 proposition. – Luka Commented May 21, 2016 at 19:59
  • Generators are merely factories for synchronous iterators. You have to bine them either with promises or with observables to handle asynchronous code. Note that Promise can emit only a single value/reason while generators are capable of emitting many values over time. More on the subject on medium – user5536315 Commented May 22, 2016 at 7:39
  • Have a look at What happens when promise is yielded in javascript?, ECMA6 generators: yield promise and Understanding code flow with yield/generators to find what you are missing: a driver that runs your generator asynchronously. They don't do that on their own. – Bergi Commented May 23, 2016 at 23:48
  • 1 Related article. – robertklep Commented May 24, 2016 at 8:18
Add a ment  | 

2 Answers 2

Reset to default 4 +50

You do not use .value at js at Question. The .value of the next() object yielded by Generator would be the Promise returned from copyFilesAndRunAnalysis, where .then() could be chained to .next().value(), Array.prototype.shift() could be used to recursively call doCar until no items remain within original or copy of cars array.

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) 
         : "plete"
})
.then(function(plete) {
  console.log(plete); 
})

Note, the same process can be achieved utilizing Promise, recursion; without using a Generator function.

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) 
         : "plete"
})
// do stuff when all items within `cars` have been 
// processed through `copyFilesAndRunAnalysis`
.then(function(plete) {
  console.log(plete); 
})

ES6 generators don't have anything to do with asynchronous execution. They provide usable mechanism for implementing async control flow in third-party code (particularly co).

It may be used like that

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

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

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

co transforms wrapped generator function into a promise and doesn't make miracles. All asynchronous actions should be performed inside generator function.

发布评论

评论列表(0)

  1. 暂无评论