2017-04-11 6 views
0

ノード環境でcronジョブで実行するプロセスを作成しています。これらのネストされた約束はなぜ機能しないのですか?

プロセスは、2つの外部サービスから2つのユーザーリストを取得し、ファイルに書き込み、比較を行います。

ユーザーのソースの1つはDiscourseフォーラムです。残念ながら、フルユーザーリストを取得するには、複数のtrust_levelリストを取得して連結する必要があります。

私はさまざまなネストされた約束とPromise.allを使用してこれを構成しました。しかし、以下の関数は、とdatabaseList.jsonの存在する前に、そのthenコールバックを呼び出すことが早すぎます...私はここで間違っていますか?

import superagent from 'superagent' 
import { writeFileSync } from 'fs' 

export default function fetchData() { 

    const process = [] 

    const databaseFetch = new Promise((resolve, reject) => { 

    superagent.get('https://our-api.com/api/1/databases/our-db/collections/users') 
     .end((error, response) => { 

     if (error) { 
      reject(error) 
     } else { 
      writeFileSync('temp/databaseList.json', JSON.stringify(response.body)) 
      resolve() 
     } 

     }) 

    }) 

    const forumFetch = new Promise((resolve, reject) => { 

    // For reference, see https://meta.discourse.org/t/how-do-i-get-a-list-of-all-users-from-the-api/24261/8 
    // We have to do this because of the way the discourse API is built 
    const discourseApiList = [ 
     'trust_level_0', 
     'trust_level_1', 
     'trust_level_2', 
     'trust_level_3', 
     'trust_level_4', 
    ] 

    let forumList = [] 

    const discoursePromises = discourseApiList.map((trustLevel) => { 

     return new Promise((resolveInner, rejectInner) => { 
     superagent.get(`https://our-website.com/forum/groups/${trustLevel}/members.json`) 
      .end((error, response) => { 

      if (error) { 
       rejectInner(error) 
       reject() 
      } else { 
       forumList = forumList.concat(response.body.members) 
       resolveInner() 
      } 

      }) 
     }) 

    }) 

    Promise.all(discoursePromises).then(() => { 
     writeFileSync('temp/forumList.json', JSON.stringify(forumList)) 
     resolve() 
    }) 

    }) 

    process.push(databaseFetch) 
    process.push(forumFetch) 

    return Promise.all(process) 

} 
+0

最後の行に戻り値がありません。 – mikeapr4

+0

@ mikeapr4いいえ、違いはありません –

+1

@ジョンドー。あまりにも早く呼ばれていますか? –

答えて

1

私にはプロミスのコードはうまく見えますが、問題は他の場所にある必要があります。

function fetchData() { 
 

 
    const process = [] 
 

 
    const databaseFetch = new Promise((resolve, reject) => { 
 
    setTimeout(function() { 
 
     console.log('resolving databaseFetch'); 
 
     resolve(); 
 
    }, Math.round(Math.random() * 10000)); 
 
    }) 
 

 
    const forumFetch = new Promise((resolve, reject) => { 
 

 
    const discourseApiList = [ 
 
     'trust_level_0', 
 
     'trust_level_1', 
 
     'trust_level_2', 
 
     'trust_level_3', 
 
     'trust_level_4', 
 
    ] 
 

 
    let forumList = [] 
 

 
    const discoursePromises = discourseApiList.map((trustLevel) => { 
 

 
     return new Promise((resolveInner, rejectInner) => { 
 

 
     setTimeout(function() { 
 
      console.log('resolving ' + trustLevel); 
 
      resolveInner(); 
 
     }, Math.round(Math.random() * 10000)); 
 

 
     }) 
 

 
    }) 
 

 
    Promise.all(discoursePromises).then(() => { 
 
     setTimeout(function() { 
 
     console.log('resolving discoursePromises'); 
 
     resolve(); 
 
     }, Math.round(Math.random() * 1000)); 
 
    }) 
 

 
    }) 
 

 
    process.push(databaseFetch) 
 
    process.push(forumFetch) 
 

 
    return Promise.all(process) 
 
} 
 

 
fetchData().then(() => console.log('finished!'));

0

あなたべきでは決して巣Promise秒、彼らの唯一の目的は、線形コードを作成することですので。私はこのように行動することをお勧め:

1- discoursePromisesを作成し、Promise.all

2-それらを解決し、forumFetchdatabaseFetchを作成し、Promise.all

とそれらを解決し、私はあなたが面白いasyncいるを見つけるかもしれないと思いますフロー制御のための素晴らしいライブラリです。特にparallelをご覧ください。 これが役立つことを願っています。

+0

いいえ、 'async.js'は約束ベースのコードでは全く助けになりません。 – Bergi

+0

もちろん、Promise OR asyncは互いの代替品なので、使用することができます。つまり、必要に応じて非同期を使用するようにコードを書き直す必要があります。 – enrichz

0

あなたは非同期ライブラリを使用したくない場合は、ネストしない約束を行い、またpromise.all、uがちょうどあなたの約束を書き込み、その流れを制御するためにそれらをチェーンすることができます:

特定の約束:

const promise1Fun =() => { 
return new Promise((resolve, reject) => { 
//do stuff 
}) 
} 


const promise2Fun =() => { 
return new Promise((resolve, reject) => { 
//do stuff 
}) 
} 

チェーンの約束:

promise1Fun.then(promise2Fun).catch((err) => console.error(err)) 
関連する問題