对象生成器函数没有执行它应该执行的操作并且没有返回任何结果。
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));
我正在尝试学习如何使用对象生成器并使用 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));