代码之家  ›  专栏  ›  技术社区  ›  que1326

在ES6生成器中,如何将值从第一个产量传递到下一个产量?

  •  2
  • que1326  · 技术社区  · 6 年前

    我搜索了真实的ES6发电机案例,但没有找到正确的解释。我想先了解一下 许诺 脚本

    假设我们有2个rest API: getUser(获取用户) getUserComments

    我们不想创建线性代码结构,避免嵌套 然后 回调功能。所以

    定义模拟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(yield getUser())获取响应并将其传递给下一个yield(yield getUserComments(userId))?

    4 回复  |  直到 6 年前
        1
  •  1
  •   dfsq    6 年前

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

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

    然后,因为您正在处理承诺,所以使用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
  •  1
  •   Me.Name    6 年前

    在某些情况下,必须等待或锁定承诺( 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
  •  0
  •   Fathy    6 年前

    你可以打电话 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
  •  0
  •   Prashanth KR    6 年前

    我试着得到你要求的结果。没有 .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);
    })();