Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
function spawn(generatorFunc) {
function continuer(verb, arg) {
var result;
try {
result = generator[verb](arg);
} catch (err) {
return Promise.reject(err);
}
if (result.done) {
return result.value;
} else {
return Promise.resolve(result.value).then(onFulfilled, onRejected);
}
}
var generator = generatorFunc();
var onFulfilled = continuer.bind(continuer, "next");
var onRejected = continuer.bind(continuer, "throw");
return onFulfilled();
}
asual commented Sep 28, 2014

I slightly modified the function for my personal needs and now it looks like this:

function spawn(generatorFunc) {
  return function() {
    function continuer(verb, arg) {
      var result;
      try {
        result = generator[verb](arg);
      } catch (err) {
        return Promise.reject(err);
      }
      if (result.done) {
        return result.value;
      } else {
        return Promise.resolve(result.value).then(onFulfilled, onRejected);
      }
    }
    var generator = generatorFunc.apply(this, arguments);
    var onFulfilled = continuer.bind(continuer, "next");
    var onRejected = continuer.bind(continuer, "throw");
    return onFulfilled();
  }
}

This basically allows me to use it with less verbose code and here is how it looks when applied to your sample:

var loadStory = spawn(function *() {
  try {
    let story = yield getJSON('story.json');
    addHtmlToPage(story.heading);
    for (let chapter of story.chapterURLs.map(getJSON)) {
      addHtmlToPage((yield chapter).html));
    }
    addTextToPage("All done");
  } catch (err) {
    addTextToPage("Argh, broken: " + err.message);
  }
  document.querySelector('.spinner').style.display = 'none';
});

Thanks for the great articles!

dbo commented Nov 2, 2014

I think there's an issue when the generator function is done. The result's value will be undefined, so it needs to be

if (result.done) {
  return arg;
}

@dbo generators don't need to return a value, in fact is better if they don't because you shouldn't depend on it. IE: if you iterate over a generator the return value will get lost.

Thanks for this gr8 article.
I am using ShowModalDialog Polyfill to make it compatible with latest versions of chrome. But when I included
'spawn *function(){}'
in my code. the jsp is not loading in IE. Can you please help? I think * is the problem. Is there any other alternative?
eval() is also not working.
Thanks for help!

boichee commented Oct 1, 2015

@Vaishali-0902:
I'd like to answer your question for you, and I'm going to try, but it's hard to know what to say. Are you working in Chrome like you state up front, or are you actually trying to do something in IE? (This makes a huge difference). Also, what version of Chrome/IE (again, big difference)?

Then, maybe you just made a typo, or maybe you just shouldn't be surprised that ES6 features aren't working properly in IE. But either way in your post you said you tried to write spawn * function()

If I'm to take you at your word, then you're missing a few basic things that would definitely cause issues:

  1. You're missing the () that would actually call the spawn function, as in spawn(function *() { } )
  2. Your syntax for creation of a generator function in ES6 isn't right. You'd create the generator like this, with the asterisk after the function.
function *() { /* generator-y stuff */ }

// So you need to write
var whatever = spawn(function *() {
  // more stuff
});

You can read more about this on MDN.

But to answer your question, per the ES6 spec, there is (sort of) an alternative to using the * syntax, the GeneratorFunction constuctor. It's definitely not ideal though, since you'd have to pass the function body as a string. Really unwieldy, and I'd really recommend you take a look at your syntax before giving this version a shot:

var foo = new GeneratorFunction(param, param1, "var x = 42; var y = 'Answer to The Ultimate Question of Life, the Universe, and Everything'; if (x === 42) return y;");

I think you'll agree that's not a way to go.


Finally, why are you using eval()? Some say it's evil. I say it can be EVIL. But seriously, read this and make sure that you're not misusing eval.

Just curious why it is called spawn... Do it has any similarity with this spawn which loads and executes a new child process..

Thank you @jakearchibald for the showModalDialog replacement. It's really helpful. Glad I was able to find this simple solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment