如何在ES6生成器中将值从第一次生成传递到下一次?

时间:2018-03-13 09:19:04

标签: javascript ecmascript-6 generator yield

我搜索了ES6发生器的真实情况并没有找到正确的解释。我试图理解第一个承诺场景。

假设我们有2个休息时间: getUser getUserComments

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

定义模拟apis

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 个答案:

答案 0 :(得分:1)

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

  

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

然后,由于您正在处理Promises,因此使用async / await将其解包为值是有意义的。

试试这个(我更正了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)
})()

答案 1 :(得分:1)

有人指出,必须等待或链接承诺(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);
})();




对于呼叫代码,首先解决/等待哪个承诺并不重要。当然,如果等待后续步骤,必须完成以前步骤的链条。 e.g:



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);
})();




答案 2 :(得分:0)

您可以使用参数调用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);

答案 3 :(得分:0)

我试图获得您需要的结果。如果没有.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);
})();