如何在 ES6 生成器中将第一个 yield 的值传递给下一个?
How to pass value from first yield to next ones in ES6 generator?
我搜索了 ES6 生成器的真实案例,但没有找到合适的解释。我试图理解第一个 Promise 场景。
假设我们有 2 个 rest api:getUser 和 getUserComments
我们不想创建一个线性代码结构来避免嵌套 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 (yield getUser()) 获取响应并将其传递给下一个 yield (yield getUserComments(userId))?
您可以将产生的结果分配给变量:
The next() method also accepts a value which can be used to modify the internal state of the generator. A value passed to next() will be treated as the result of the last yield expression that paused the generator. (From 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)
})()
你可以用一个参数调用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);
我已经尝试得到您需要的结果。没有 .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);
})();
在某些时候,必须等待或链接 promise (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);
})();
对于调用代码,哪个 promise 先 resolved/awaited 并不重要。当然,如果等待后面的步骤,链条必须为前面的步骤完成。例如:
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);
})();
我搜索了 ES6 生成器的真实案例,但没有找到合适的解释。我试图理解第一个 Promise 场景。
假设我们有 2 个 rest api:getUser 和 getUserComments
我们不想创建一个线性代码结构来避免嵌套 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 (yield getUser()) 获取响应并将其传递给下一个 yield (yield getUserComments(userId))?
您可以将产生的结果分配给变量:
The next() method also accepts a value which can be used to modify the internal state of the generator. A value passed to next() will be treated as the result of the last yield expression that paused the generator. (From 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)
})()
你可以用一个参数调用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);
我已经尝试得到您需要的结果。没有 .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);
})();
在某些时候,必须等待或链接 promise (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);
})();
对于调用代码,哪个 promise 先 resolved/awaited 并不重要。当然,如果等待后面的步骤,链条必须为前面的步骤完成。例如:
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);
})();