2016-12-27 18 views
3

私は、より多くのデータを取得するためのカーソルを返すAPIを持っています。私はこのようにそれを嘲笑しました:私は何をしようとしているJavaScriptで非同期ジェネレータを使用するにはどうすればよいですか?

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

は、私は、このAPIと対話するために、発電機と一緒に非同期/のawait使用することができる方法を見つけ出すです。

ここで私が試作さてきたものは基本的です:

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]ですべてのデータを取り出すことはかなり気が楽です。

問題が解決しない場合があります。

❯❯❯ 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 

しかし、これは可能なはずであるように私は本当に感じ:Apprentlyあなたはfunction*asyncを使用することはできません。 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

拡散要素を使用せずにジェネレータ関数をパラメータとして渡すことができます。Promise.all()は、yieldが返すパラメータとして反復可能性を受け入れます。 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" ] 
} 
関連する問題