2017-09-15 7 views
0

私は以下の機能を持っています。これは属性の配列を取得し、ループ内で繰り返し処理して、すべての単一の属性をデータベースに格納します。しかし、ループがawait文で自動的に殺される:現代のJavascriptでfor-loopを "中断"してしまうのはなぜですか?

async function importAttributeRecords(attributeValues, languageId, attributes, dataStorage, tx) { 
    for(let attr of attributes) { 
    console.log("Persist", attr) 
    try { 
     await importAttributeRecord(attributeValues, languageId, attr, dataStorage, tx) 
    } 
    catch(err) { 
     console.log(err); 
    } 
    console.log("After persisting"); 
    } 
} 

awaitへの最初の呼び出しが実行されますが、それ後の第二console.log文は表示されません。 また、ループはすぐに終了します。

私のimportAttributeRecord()のような機能をループで同期的に実行するには、どうすれば約束を返すことができますか? そしてなぜ "await"をループに使うのが危険ですか?

+0

2つ目のログを出力して、それを出力することを意味しますか?例外がスローされますか? – k0pernikus

+4

さらに[mcve]が必要です。 – melpomene

+4

ループは強制終了されません。それは保留になり、約束を待っているときに再開します。約束は非同期です。それらを同期として扱うことはできません。 –

答えて

1

これは「カテゴリエラー」と説明することができます。 A forループは基本的に同期プログラミングのアイデアであり、アレイや他のインデックスされたエンティティ内でそれぞれのことを次々にやりながら待っています。

asyncが実装する非同期プログラミングは、異なるアプローチです。それを使用する最も完全な方法は、前の状況と後の状況との間の関係を表現し、その言語がタイミングを処理し、おそらく同時並行的に実行させることです。このような状況のために

は、ここにあなたがそれを行うだろうかです:

async function importAttributeRecords(attributeValues, languageId, attributes, dataStorage, tx) { 
    return Promise.all(attributes.map(attr => { 
    console.log("Initiate persist", attr); 
    return importAttributeRecord(attributesValues, languageId, attr, dataStorage, tx).then(result => { 
     console.log("After persisting", attr, result); 
    }).catch(err => { 
     console.log("Error: ", attr, err); 
    })); 
    }); 
} 

あなたはimportAttributeRecordsが今約束の配列を返すので、それは合法的asyncであることに注意します。このコードが少し短くなっています。

+0

1.この例では、 'importAttributeRecord'からの約束をまったく待っていません。あなたは 'Promise.all'を忘れましたか? 2.問題のコードに何も問題はありません。ループで 'await'を使うのは、それが連続して実行されるので勧められないかもしれませんが、それはうまくいかないとは限りません。 OPのコードを破っているものであれ、あなたのコードも壊れてしまいます。 'for'ループは基本的に_serial_ですが、基本的に_synchronous_ではありません。 – loganfsmyth

+0

@loganfsmyth 1.誰がこれの呼び出し者が 'Promise.race'を使いたくないと言っていますか?あなたはその可能性を忘れましたか?さらに、 '.then'の結果を返すことは、イディオムではなく、' async'と互換性があると思いますか? *シリアル*が非同期*で慣用的だと思っていますか? –

+1

"これを呼び出す人はPromise.raceを使いたくないと言っています。"元の質問には、各項目を非常にはっきりと実行するループがあり、それらをすべて待っているからです。私のポイントは、 'return attributes.map(' return attributes.map( '' return attributes.map( '' '' '' '' '' '' '' '' '' '' '' "forループは基本的には同期プログラミングのアイデア"ですが、私の主張は順序の振る舞いを定義するループです。コードはループの使用とは無関係に同期または非同期にすることができます – loganfsmyth

関連する問題