更好地理解JavaScript的yield

3

我在我的Koa应用程序中有以下代码:

exports.home = function *(next){
  yield save('bar')
}

var save = function(what){
  var response = redis.save('foo', what)
  return response
}

但我遇到了以下错误:TypeError: 您只能yield函数、promise、generator、数组或对象,但传递了以下对象:"OK"

现在,"ok"是redis服务器的响应,这很合理。但是我无法完全理解生成器与此类函数的概念。需要帮忙吗?


你使用的是哪个 Redis 包?我猜你正在使用常规的 Redis npm 模块,它需要一个回调函数。试试 co-redis,它返回一个 Promise。 - James Moore
哦,不,我正在使用coRedis,连接的代码如下:var redis = require("redis"), coRedis = require("co-redis"), db = redis.createClient(), dbCo = coRedis(db); module.exports = dbCo;(在另一个文件中) - john doe
2个回答

3

由于SAVE命令是同步的,所以你不会得到save('bar')的结果。(你确定要使用save吗?)

既然它是同步的,那么你应该将这个操作改为:

exports.home = function *(next){
  yield save('bar')
}

转换为:

exports.home = function *(next){
  save('bar')
}

而且它会阻塞执行,直到完成。

几乎所有其他Redis方法都是异步的,因此您需要使用yield命令。

例如:

exports.home = function *(next){
  var result = yield redis.set('foo', 'bar')
}

谢谢您的澄清。所以在这种情况下我不应该使用yield吗?如果我想要做一个var res = get('foo'); this.body=res,那我不需要在调用上使用yield吗? - john doe
你需要使用异步函数(这是 Redis API 的大部分)。我认为 save 是同步的(一种特殊情况),这可能让你感到困惑。因为 Redis 的 GET 是异步的,所以你需要使用 yield:var res = yield redis.get('foo')。我之所以知道 redis.save 是同步的,是因为文档页面上用粗体字标出了:http://redis.io/commands/save。这有点像 Node 中 var text = fs.readFileSync('README.md')(同步)和 fs.readFile('README.md', function(text) { ... })(异步)之间的区别。这样说是否更容易理解? - danneu

0

根据文档,yield 应该在生成器函数内使用。 其目的是返回迭代的结果以在下一次迭代中使用。

就像这个例子(摘自文档):

function* foo(){
  var index = 0;
  while (index <= 2) // when index reaches 3, 
                     // yield's done will be true 
                     // and its value will be undefined;
    yield index++;
}

var iterator = foo();
console.log(iterator.next()); // { value:0, done:false }
console.log(iterator.next()); // { value:1, done:false }
console.log(iterator.next()); // { value:2, done:false }
console.log(iterator.next()); // { value:undefined, done:true }

谢谢你的回答。函数调用实际上在生成器函数内部,只是我忘记写了。请检查我的编辑。 - john doe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接