【问题标题】:How to pass value from first yield to next ones in ES6 generator?如何在 ES6 生成器中将值从第一个收益传递到下一个收益?
【发布时间】:2018-08-21 11:35:06
【问题描述】:

我搜索了真实案例 ES6 生成器,但没有找到正确的解释。我正在尝试理解第一个 Promise 场景。

假设我们有 2 个 rest api:getUsergetUserComments

我们不想创建一个线性代码结构来避免嵌套的 then 回调函数。所以...

定义模拟 API

function getUser () {
    return new Promise(function(resolve, reject) {
       return setTimeout(function() { resolve({id: 1, label: 'John'}); }, 200);
    });
}

function getUserComments(userId) {
    return new Promise(function(resolve, reject) {
      return setTimeout(function() {resolve({comments: 'comments', userId: userId}); }, 200);
    });
}

定义生成器

function* generator () {
  yield getUser();
  yield getUserComments(userId); // userId represents data from first request / first yield how should I pass it ?!
}

var g = generator();
var first  = g.next(1);
var second = g.next(2);

如何从第一个收益 (yield getUser()) 获得响应并将其传递给下一个收益 (yield getUserComments(userId))?

【问题讨论】:

  • 修复你的代码,它是无效的。

标签: javascript ecmascript-6 generator yield


【解决方案1】:

您可以将产生的结果分配给变量:

next() 方法还接受一个可用于修改生成器内部状态的值。传递给 next() 的值将被视为暂停生成器的最后一个 yield 表达式的结果。 (来自MDN, Advanced generators

那么既然您正在处理 Promises,使用 async/await 将其解包为 value 是有意义的。

试试这个(我稍微修正了 setTimeout 参数):

async function getUser() {
  return new Promise(function(resolve, reject) {
    setTimeout(resolve, 0, {
      id: 1,
      label: 'John'
    })
  })
};

async function getUserComments(user) {
  return new Promise(function(resolve, reject) {
    setTimeout(resolve, 0, {
      ...user,
      comments: 'comments',
    }, 'userComments');
  });
}

function* generator () {
  const user = yield getUser();
  yield getUserComments(user);
}

(async function () {
  const g = generator();
  const user = await g.next().value
  const comments = await g.next(user).value

  console.log(comments)
})()

【讨论】:

    【解决方案2】:

    在某些时候,必须等待或链接承诺 (then)。目标是完全防止链接还是仅在实现代码中?否则,生成器本身可以进行链接,因此调用代码不必:

    function* generator () {
        const u = getUser(), c = u.then(userId => getUserComments(userId));
      yield *[u,c];
    }
    

    示例:

    function getUser () {
        return new Promise(function(resolve, reject) {
           setTimeout(function() { resolve({id: 1, label: 'John'}); }, 200);
        });
    }
    
    function getUserComments(userId) {
        return new Promise(function(resolve, reject) {
          setTimeout(function() {resolve({comments: 'comments', userId: userId}); }, 200);
        });
    }
    
    
    function* generator () {
    	const u = getUser(), c = u.then(userId => getUserComments(userId));
      yield *[u,c];
    }
    
    
    (async function(){
    	var g = generator();
      var first  = await g.next().value;
      var second = await g.next().value;
      console.log(first, second);
    })();

    对于调用代码,首先解决/等待哪个承诺并不重要。当然,如果等待后面的步骤,则必须为前面的步骤完成链。例如:

    function getUser () {
        return new Promise(function(resolve, reject) {
           setTimeout(function() { resolve({id: 1, label: 'John'}); }, 200);
        });
    }
    
    function getUserComments(userId) {
        return new Promise(function(resolve, reject) {
          setTimeout(function() {resolve({comments: 'comments', userId: userId}); }, 200);
        });
    }
    
    
    function* generator () {
    	const u = getUser(), c = u.then(userId => getUserComments(userId));
      yield *[u,c];
    }
    
    
    (async function(){
    	var g = generator();
      var prom  = g.next().value;  
      var second = await g.next().value;
      
      console.log(await prom, second);
    })();

    【讨论】:

      【解决方案3】:

      您可以使用参数调用next,并使用yield 获取它。示例:

      function* generator () {
        var userId = yield getUser();
        yield getUserComments(userId); // userId represents data from first request / first yield how should I pass it ?!
      }
      
      var g = generator();
      var first  = g.next();
      var userId = getUserId(first);
      var second = g.next(userId);
      

      【讨论】:

        【解决方案4】:

        我已尝试获得您需要的结果。没有.then(),我无法得到getUser()的结果

        function getUser () {
            return new Promise(function(resolve, reject) {
               return setTimeout(function() { resolve({id: 1, label: 'John'}); }, 200);
            });
        }
        
        function getUserComments(userId) {
            console.log(userId)
            return new Promise(function(resolve, reject) {
              return setTimeout(function() {resolve({comments: 'comments', userId: userId}); }, 200);
            });
        }
        
        function* generator () {
          var userId = yield getUser();
          yield getUserComments(userId); // userId represents data from first request / first yield how should I pass it ?!
        }
        
        var g = generator();
           
        (async function(){
          var first = await g.next();
          var userId = await first.value.then((res)=>{ return res.id });
          g.next(userId);
        })();

        【讨论】:

          猜你喜欢
          • 2013-07-03
          • 1970-01-01
          • 2014-08-22
          • 2011-05-14
          • 2013-09-28
          • 2017-12-09
          • 2019-04-12
          • 1970-01-01
          • 2020-04-21
          相关资源
          最近更新 更多