2017-10-12 19 views
2

私は次のコードで私のカスタムモジュールを持っていた:私のモジュールの外部関数を呼び出す場合、それが実行している間、私はエラーを得たの内側に私が呼ばれるしかし、もし、うまく働いた正しい非同期機能輸出

module.exports.PrintNearestStore = async function PrintNearestStore(session, lat, lon) { 
... 
} 

私は、構文を変更し

(node:24372) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): ReferenceError: PrintNearestStore is not defined

module.exports.PrintNearestStore = PrintNearestStore; 

var PrintNearestStore = async function(session, lat, lon) { 

} 

それは細かい内部のモジュールを動作するように始めたが、OU失敗しますモジュールtside - 私はエラーを得た:

(node:32422) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: mymodule.PrintNearestStore is not a function

だから私はにコードを変更しました:

module.exports.PrintNearestStore = async function(session, lat, lon) { 
    await PrintNearestStore(session, lat, lon); 
} 

var PrintNearestStore = async function(session, lat, lon) { 
... 
} 

そして今、それはすべての場合に動作します:内側と外側。しかし、セマンティクスを理解したいと思ったら、それをもっと美しく短く書く方法があるのでしょうか? asyncは、モジュールの内部と外部(エクスポート)モジュールの両方を正しく定義して使用する方法ですか?

答えて

7

これは実際には特に非同期機能を特別に持っていません。関数を内部で呼び出す場合は、をエクスポートし、を最初にと定義してエクスポートします。

async function doStuff() { 
    // ... 
} 
// doStuff is defined inside the module so we can call it wherever we want 

// Export it to make it available outside 
module.exports.doStuff = doStuff; 

あなたの試みと問題の説明:

module.exports.PrintNearestStore = async function PrintNearestStore(session, lat, lon) { 
... 
} 

これは、モジュール内の関数を定義していません。関数定義は、関数の式です。関数式の名前は、関数自体の内部にのみ変数を作成します。シンプルな例:

var foo = function bar() { 
 
    console.log(typeof bar); // 'function' - works 
 
}; 
 
foo(); 
 
console.log(typeof foo); // 'function' - works 
 
console.log(typeof bar); // 'undefined' - there is no such variable `bar`

Named function expressions demystified参照してください。どこでもmodule.exports.PrintNearestStoreを参照すれば、もちろん関数を参照することができます。


module.exports.PrintNearestStore = PrintNearestStore; 

var PrintNearestStore = async function(session, lat, lon) { 

} 

これはほとんど OKです。問題は、module.exports.PrintNearestStoreに割り当てたときにPrintNearestStoreの値がundefinedになることです。実行順序は次のとおりです。

var PrintNearestStore; // `undefined` by default 
// still `undefined`, hence `module.exports.PrintNearestStore` is `undefined` 
module.exports.PrintNearestStore = PrintNearestStore; 

PrintNearestStore = async function(session, lat, lon) {} 
// now has a function as value, but it's too late 

よりシンプルな例:

var foo = bar; 
 
console.log(foo, bar); // logs `undefined`, `undefined` because `bar` is `undefined` 
 
var bar = 21; 
 
console.log(foo, bar); // logs `undefined`, `21`

あなたが期待通りに動作するでしょう順序を変更した場合。時間によってmodule.exports.PrintNearestStoreに割り当てられた機能が実行されるので、これは動作


module.exports.PrintNearestStore = async function(session, lat, lon) { 
    await PrintNearestStore(session, lat, lon); 
} 

var PrintNearestStore = async function(session, lat, lon) { 
... 
} 

PrintNearestStore、その値としての機能を有しています。外部の関数式なので、この名前は使用できません - PrintNearestStore

よりシンプルな例:

var foo = function() { 
 
    console.log(bar); 
 
}; 
 
foo(); // logs `undefined` 
 
var bar = 21; 
 
foo(); // logs `21`

+0

は、私が見る、ありがとうございました。関数定義( 'var'を取り除いたもの)と' module.exports'を関数定義として定義しました。内部呼び出し関数の定義の順序は重要ではないことが分かります。関数定義の前に関数呼び出しがありますが、 'module.exports'では重要です。 –

+2

@AlekseyKontsevich:FWIW、ソースコード内の*行*が*前の行Bであるということは、行Aが*実行前*行Bより前に*実行されていることを意味するものではありません。もちろん、関数を呼び出す前に関数定義を評価しなければなりません。しかし、巻上げのために実行順序がJSでは明白ではないかもしれません。 –

2

最初のケースでエラーが発生しました。

2番目の場合のエラー:変数を使用する代わりに関数宣言。この場合、変数PrintNearestStoreの宣言が呼び出されますので、の前にの行var PrintNearestStore = ...を使用できますが、この場合値はで定義されていません。です。

ので、最も簡単な解決策は、このような第二の変形変更:

module.exports.PrintNearestStore = PrintNearestStore; 

async function PrintNearestStore(session, lat, lon) { 

} 
+0

動作しません:まず関数定義を入れてから、 'module.exports'を入れる必要があります。 –

+3

@AlekseyKontsevich、いいえ、私の解決策は期待どおりに動作します:https://repl.it/M8Jn – Grundy

+0

私は上記のように、ノード8.6でそのようなコードに対して 'UnhandledPromiseRejectionWarning'を取得しました。私は関数定義を最初に置き、次に 'module.exports'を修正します。 –