如何同时在生成器中映射异步调用的结果?
var generator = (function *() {
var lotsOfThings = yield asyncTask.call(generator);
var mappedResults = yield lotsOfThings.map(thing => {
// fails with a syntax error unless you do a `for…of` loop, but also doesn’t run concurrently regardless
return (yield asyncTask.call(generator, thing));
});
// then do something with mappedResults
})();
generator.next();
function asyncTask(…query) {
somethingAsync(…query, (err, res) => this.next(res));
}
此外,即使在常规for...of
循环中,也无法同时运行每个asyncTask
。 yield
将导致每个任务之间的暂停,实质上是发出同步AJAX请求。理想情况下,你希望它像承诺一样工作,就像这个范例:
// these tasks will run concurrently (unlike the above example)
let promises = someThings.map(thing => {
return new Promise((resolve, reject) => {
somethingAsync((err, res) => {
resolve(res);
});
});
});
Promise.all(promises).then(/* do stuff */);
promise方法可能会导致所有嵌套的毛病,但好处是异步任务可以同时运行...而生成器看起来不错,但循环任务不是并发的。有什么想法吗?
答案 0 :(得分:1)
我试图在没有第三方库的情况下绘制类似的东西:
// Async runner
function async(generator){
var process = function(result){
if (result.done) {
return;
}
(Array.isArray(result.value) ? Promise.all(result.value) : result.value).then(function(value){
process(sequence.next(value));
});
};
var sequence = generator();
var next = sequence.next();
process(next);
};
// Generator function
var generator = function* () {
var list = yield getList();
console.log(list); // outputs [1, 2, 3, 4, 5]
var details = yield list.map(p => getDetails(p));
console.log(details); // outputs [11, 12, 13, 14, 15]
}
// Your async requests go here
function fakeAsync(f) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
f(resolve);
}, 500);
});
}
function getList() {
return fakeAsync(function(resolve) {
resolve([1, 2, 3, 4, 5]);
});
}
function getDetails(i) {
return fakeAsync(function(resolve) {
resolve(i + 10);
});
}
async(generator);
这是你想要实现的目标吗?
答案 1 :(得分:0)
我正在寻找的答案可以通过co来实现。
<property name ="Web Application" value="\Fxnet2\Web\webpl\" />
<property name="Web Service" value="\FXnet2\Web\FXnet_SC_WS\" />
修改:已将co(function* () {
// maybe we need a token from our API before we can do anything
let token = yield new Promise((resolve, reject) {
getToken(token => resolve(token));
});
// these run in parallel
var queries = yield [
request('/route', token),
request('/another-route', token)
];
// [[], []] becomes [...]
return _.flatten(queries);
});
// our async request function returns a promise
function request(route, token) {
return new Promise((resolve, reject) => {
somethingAsync(route, token, (res) => {
resolve(res);
});
});
}
更改为somethingAsync
,因为在我的实际案例中,它已调用尚未返回的第三方API一个承诺。