我试图学习如何使用对象生成器并使用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;
}
答案 0 :(得分:2)
我相信你正在寻找promises,而不是发电机功能。生成器函数返回 IterableIterator 对象。这些对象遵循iterator protocol,这意味着它们具有next()
方法,该方法返回具有value
字段和done
布尔字段的对象。它们也遵循iterable protocol,这意味着它们有一个特殊的@@iterator
方法,它返回一个迭代器对象(在这种情况下,它返回自己,因为它是它自己的迭代器)。
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));
答案 1 :(得分:1)
首先,我认为你必须检查一些生成器教程。对于使用生成器,您必须首先创建生成器然后使用它,以便您的代码变为如下:
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
函数的第一个参数传递,并且您的next函数的返回值是具有以下形式的对象:
{
value: ...,
done: false
}
并且在您的应用程序中是从超时函数返回的对象,为了完成您的功能,您必须再次调用next()
。
请注意,您的生成器中的yield
命令会向您返回传递给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。
除了生成器,您还可以使用ECMA2017的原生js或async
功能来管理控制流程。