2016-12-27 82 views
3

我有一个api即将返回一个游标来获取更多的数据。我嘲笑它是这样的:如何在JavaScript中使用异步生成器?

function fetch(n) { 
    return Promise.resolve({ 
    results: [n], 
    next: next < 10 && n + 1, 
    }) 
} 

我想要做的就是找出我怎么能以与此API交互使用异步/等待着发电机一起。

这里基本上是我所原型:

async function* api(url) { 
    let result = await fetch(url) 
    yield result 
    while (result.next) { 
    result = await fetch(result.next) 
    yield result 
    } 
} 

的想法是,我应该能够为了通过游标进行迭代,以创建从发电机异步发电机和产量:

async function main() { 
    const gen = api(0) 
    const zero = await gen.next() 
    console.log(zero.result) 
    const one = await gen.next() 
    console.log(one.result) 
    const rest = await Promise.all([...gen]) 
    console.log(rest.map(r => r.result)) 
} 

所有的事情都考虑到了,我认为这是处理分页数据并能够使用[...gen]取出所有数据的非常可爱的方式,非常酷。

唯一的问题是,它不起作用! Apprently你不能function*使用async

❯❯❯ node --version 
v7.0.0 
❯❯❯ node --harmony --harmony-async-await async-generator.js 
/Users/chetcorcos/code/async-generator.js:11 
async function* api(url) { 
      ^
SyntaxError: Unexpected token * 
    at Object.exports.runInThisContext (vm.js:76:16) 
    at Module._compile (module.js:545:28) 
    at Object.Module._extensions..js (module.js:582:10) 
    at Module.load (module.js:490:32) 
    at tryModuleLoad (module.js:449:12) 
    at Function.Module._load (module.js:441:3) 
    at Module.runMain (module.js:607:10) 
    at run (bootstrap_node.js:382:7) 
    at startup (bootstrap_node.js:137:9) 
    at bootstrap_node.js:497:3 

但我真的觉得这应该是可能的。有一个名为co的流行图书馆,我一直在探索,但我不认为这就是我想要的。

任何想法如何让这个“异步发电机”的概念工作?

+4

看一看即将到来的建议https://github.com/tc39/proposal-async-iteration。你可以使用Babel的['babel-plugin-transform-async-generator-functions'](https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-async-generator-函数)变换 –

+0

正在使用'async/await'部分的要求吗? – guest271314

+0

@FelixKling,建议是史诗般的。谢谢! – Chet

回答

0

您可以通过调用generator函数作为参数,而不使用spread元素,Promise.all()接受yield返回的iterable作为参数。请注意,Promise.all()不会按顺序排序或拒绝传递的Promise对象,但会按照与传递的迭代中的元素相同的顺序返回结果数组。

let api = (value) => { 
 
    return new Promise((resolve, reject) => { 
 
    setTimeout(() => { 
 
     resolve(value) 
 
    }, Math.floor(Math.random() * 3500)) 
 
    }) 
 
}; 
 

 
let values = [1, 2, 3]; 
 
let results = []; 
 
let gen = function* gen(fn, props) { 
 
    let i = 0; 
 
    do { 
 
    yield fn(props[i]).then(res => {console.log(res); return res}); 
 
    ++i; 
 
    } while (i < props.length); 
 
} 
 

 
Promise.all(gen(api, values)) 
 
.then(data => console.log("complete:", data)) 
 
.catch(err => console.log(err));

0

为此,可以使用巴贝尔插件transform-async-generator-functions做。

用法是这样的:

const g = async i => [ 1, 2, 3 ] 
    .map(x => x * 10 ** i); 

const f = async function *() { 
    for (let i = 0; i < 10; i++) { 
    const xs = await g(i); 
    for (const x of xs) { 
     yield x; 
    } 
    } 
}; 

const main = async() => { 
    for await (const x of f()) { 
    console.log(x); 
    } 
}; 

main().catch(e => console.error(e)); 

这里是an example repo展示了如何设置你的项目。

的重要组成部分,是.babelrc文件:

{ 
    "presets": [ "env" ], 
    "plugins": [ "transform-async-generator-functions" ] 
} 
相关问题