对象生成器函数没有执行它应该执行的操作并且没有返回任何结果。

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

我正在尝试学习如何使用对象生成器并使用 yield 命令在我的 nodejs 控制器中执行一些同步操作。

我希望它首先执行 FOO 调用,然后在返回时执行 BAR 调用。

在这种情况下,我希望控制台显示

Hello FOO
Hello BAR

但我得到的只是

Result [object Generator]
Result [object Generator]

我什至没有得到函数内部的 console.logs。

  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;
}

首先,我认为您必须查看一些生成器教程。要使用生成器,您必须首先创建生成器然后使用它,这样您的代码就会变成这样:

var findUser = findUser("FOO");
var myResult = findUser.next().value;
console.log("Result " + myResult );
findUser.next();


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;
}

请注意,您必须将回调函数作为 setTimeout 函数的第一个参数传递,并且您的下一个函数的 return 值是一个具有以下形式的对象:

{
  value: ...,
  done: false
}

并且在您的应用程序中是一个从超时函数 return 编辑的对象,为了完成您的函数,您必须再次调用 next()。 请注意,您的生成器中的 yield 命令 return 向您发送了传递给 next().

的内容

最后让我们回顾一下使用生成器创建控制流的一些方法:

function asyncFlow(generatorFunction) {
  function callback(err) {
    if (err) {
      return generator.throw(err);
    }
    const results = [].slice.call(arguments, 1);
    generator.next(results.length > 1 ? results : results[0]);
  }
  const generator = generatorFunction(callback);
  generator.next();
}

asyncFlow(function* (callback) {
  console.log('1. Hello');
  yield setTimeout(callback, 2000);
  console.log('2. 2000ms');
  yield setTimeout(callback, 1000);
  console.log('3. 1000ms');
});

co 是一个很好的基于生成器的控制流库,你可以找到它的详细信息 here.

除了生成器,您还可以使用原生 js 或 ECMA2017 的 async 功能来管理您的控制流。

我相信您正在寻找 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,这意味着他们有一个特殊的 @@iterator 方法,该方法 returns 一个迭代器对象(在这种情况下,它 returns 本身因为它是它自己的迭代器)。

另一方面,Promises 代表一个目前还不存在但可能在未来某个时间存在的值。 ES6 还为我们提供了 async functions,它简化了使用带有 await 关键字的承诺。以下是您的代码使用异步函数时的样子:

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();

如果你不想使用async/await语法,下面是等价的:

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));