2016-01-12 20 views
7

私は基本的にJavaScriptを使用する方法を知っていても、JavaScriptのasync functionが技術的に何であるかを理解しようとしています。ES7非同期機能と約束の技術的な違いは?

async function asyncFunc() { 
    // nop 
} 

var fooPromise = new Promise(r => setTimeout(r, 1)); 

console.clear(); 

console.log("typeof asyncFunc is", typeof asyncFunc); // function 
console.log("typeof asyncFunc.next is", typeof asyncFunc.next); // undefined 
console.log("typeof asyncFunc.then is", typeof asyncFunc.then); // undefined 

console.log("typeof fooPromise is", typeof fooPromise); // object 
console.log("typeof fooPromise.next is", typeof fooPromise.next); // undefined 
console.log("typeof fooPromise.then is", typeof fooPromise.then); // function 

はまだ、それは間違いなく可能です:

多く紹介非同期に/ async機能は基本的には約束ですが、それは明らかにケース(Babel6-transpiled codeでない少なくとも)ではないことを信じて作る待ちます例えば、await fooPromise()のように、awaitに約束してください。

  • は、それ自身のものasync funtionですとawaitは単に約束と互換性のですか?

  • 実行中(Babel互換の方法で)簡単なfunctionasync functionを区別する方法はありますか?

答えて

9

非同期機能は約束を返す機能です。それはあなたが次々に起こって非同期アクションの束を持っている場合に役立ちます:

function asyncFunc() { 
    return doSomethingAsync() // doSomethingAsync() returns a promise 
    .then(() => { 
     // do some stuff 
     return doSomethingElseAsync(); // returns a promise 
    }) 
    .then(something => { 
     // do some stuff 
     return doSomethingElseEntirelyAsync(something); // returns a promise 
    }); 
} 

は、それはかなり良く読み、あなたが試してみるような通常のツールを使用することができます

async function asyncFunc() { 
    await doSomethingAsync(); // awaits for a promise 
    // do some stuff 
    let something = await doSomethingElseAsync(); // awaits for a promise 
    // do some stuff 
    return doSomethingElseEntirelyAsync(something); // returns the final promise 
    // Note that even if you return a value, like return 5, the function as a whole 
    // still returns a promise! 
} 

に切り替えます/ catchとforループが非同期であっても、それらと連動します。

非同期機能は、ではありません。連続した非同期アクションが多数ある特定のケースを処理するために、約束事に代わるものがあります。

awaitは「この約束のために待つ」だけで、基本的なので、あなたはまだPromise.all()Promise.race()のようなクールな集計メソッドを使用して、いくつかの(またはいくつかの最初の)約束の結果を待つことができます。

クラスのように、非同期関数はPromisesの上にある砂糖なので、ランタイムでは2つを区別する方法に慣れていません。 (関数の.toStringを使用し、結果を解析するようなハックがあるかもしれませんが、私はそれらを数えません)。

+0

ありがとうございます。したがって、本質的に、 'asyncFunc'はPromiseではありませんが、' asyncFunc() 'は - または他の言葉でです:' typeof asyncFunc()。then == "function" ' –

+0

これはまさに正しいものです。 –

0

カップルasync/awaitは、非同期コードを同期スタイルで書くことができるメカニズムであり、私の謙虚な意見ではこれまで非同期コード(this articleも参照)を処理するための最もシンプルで読みやすい構文です。構文のパワーは実際にawaitの仕組みにあります。しかし、関数の本体の内部にawaitを使用するには、関数の先頭にasyncを付ける必要があります。

さらに詳しい情報が必要な場合は、spec for async/await hereがあります。

現在のBabel 5の実装は、https://github.com/facebook/regeneratorに基づいています。あなたがFacebookのコードを見つけるバベルのbabel-regenerator-runtimeパッケージに掘る場合

function asyncFunc(which, one, two) { 
    return regeneratorRuntime.async(function asyncFuncMaybe$(context$1$0) { 
... 

:あなたがtranspiled codeで見ることができるように機能をにコンパイルされます。 line 205であなたが見つける:ES5にasync/awaitバベルのニーズをtranspileするために

// Note that simple async functions are implemented on top of 
// AsyncIterator objects; they just return a Promise for the value of 
// the final result produced by the iterator. 
runtime.async = function(innerFn, outerFn, self, tryLocsList) { 
... 

たちは、関数の実行時にどこ私たちはトラックを保つことができるとAsyncIteratorは、トラックを保つオブジェクトであるように、コードを再配置するために行いますその州の

Babel 6にはさらに多くのオプションがあり、使用する実装を選択できます。

  • async/awaitそれ自身のものの両方です。だからあなたの質問に関するTranspile Async Await proposal with Babel.js?

    参照してください。スペックによれば、彼らは約束で働かなければならない。特にawaitを約束し、async関数を実行すると、約束が返されます。

  • async関数は、約束を返す関数に変換されるため、約束を返す非同期関数と区別するための直接的な方法はありません。 fooPromiseは、fooPromiseFuncasyncFuncを将来のブラックボックスと区別できないようにするとvar fooPromiseFunc = function() {return new Promise(r => setTimeout(r, 1))};のようになります。それらは両方とも約束を返す関数です。実行時にasyncと非同期関数を区別したい理由は何ですか?実際には同じ方法で使用することができます。なぜなら、なぜあなたはそれらを別々に脅かさなければならないのか分かりません。デバッグの目的で、関数がasyncと定義されているかどうかを実際に調べる必要がある場合は、(asyncFunc+"").indexOf('regeneratorRuntime.async') > 0やより正確な正規表現などを使用できます。しかし、それは実際には ハッキーです、私はデバッグや研究の外で文脈で使用しません。
+0

詳細な説明をいただきありがとうございます。実際には、通常のコールバックをPromisesと区別する必要がありました。(最終的には、 'express 'をPromise/asyncと互換性があるようにしたいのですが、なぜなら、それは実行時に非同期関数と非同期関数を区別したいからです。自動方法)。今私は物事がどのように動作するかを知っているので、それは私にはっきりとしており、実際には 'express 'のために完全に動作する(実験的な)パッチを作ることができました。 –

+0

この2つのリンクは便利です:https://strongloop.com/strongblog/async-error-handling-expressjs-es7-promises-generators/そしてhttps://github.com/luin/express-promise –

+0

これらのリンクをありがとう。私はこの質問を投稿する前にそれらを既に知っていました。答えの助けを借りて、明示的なラッパー関数の使用を避ける方法を見つけましたが、まったく同じ結果が得られました。 –

関連する問題