Search code examples
javascriptnode.jsyield

Object generator function not doing what it should and returning no result.


Im trying to learn how to use object generators and use the yield command to do some synchronous operations in my nodejs controller.

I want this to first execute the FOO call, and THEN when returned, execute the BAR call.

In this case I was expecting the console to show

Hello FOO
Hello BAR

But all I get is

Result [object Generator]
Result [object Generator]

I dont even get the console.logs inside the function.

  var myResult = findUser1("FOO")
  console.log("Result " + myResult )

  myResult = findUser1("BAR")
  console.log("Result " + myResult )

function* findUser1(UID) {
    var user1 = yield setTimeout("Hello " + UID, 2000);
    console.log("This should be shown AFTER user1 has a result");
    console.log(user1);
    return user1;
}

Solution

  • I believe you are looking for promises, not generator functions. Generator functions return IterableIterator objects. These objects adhere to the iterator protocol, meaning they have a next() method that returns an object with a value field and a done boolean field. They also adhere to the iterable protocol, meaning they have a special @@iterator method that returns an iterator object (in this case, it returns itself since it is its own iterator).

    Promises, on the other hand, represent a value that does not exist yet but may exist at some time in the future. ES6 also gives us async functions which simplify using promises with an await keyword. Here's how your code might look using async functions:

    async function findUser(id) {
      const user = await new Promise((resolve, reject) => {
        setTimeout(() => resolve("Hello " + id), 2000);
      });
      console.log("This should be shown AFTER user has a result");
      console.log(user);
      return user;
    }
    
    async function getUsers() {
      const user1 = await findUser("FOO");
      console.log("Result " + user1);
      const user2 = await findUser("BAR");
      console.log("Result " + user2);
    }
    
    getUsers();
    

    If you don't want to use async/await syntax, the following is equivalent:

    function findUser(id) {
      return new Promise((resolve, reject) => {
        setTimeout(() => resolve("Hello " + id), 2000);
      }).then((user) => {
        console.log("This should be shown AFTER user has a result");
        console.log(user);
        return user;
      });
    }
    
    findUser("FOO")
      .then(user1 => console.log("Result " + user1))
      .then(() => findUser("BAR"))
      .then(user2 => console.log("Result " + user2));