2017-09-27 7 views
0

データを表示するためにmongoDBクエリを処理する必要があるかなり複雑なプロジェクトに取り組んでいます。現在、大量のデータセットに対してクエリを実行する場合、ページが読み込まれるとすぐにすべてのデータが表示されるわけではありません。今のところ、私はnext()関数を使う前に、タイムアウト関数を設定してこの問題を解決しました。続行する前にmongoDBクエリのすべての項目が処理されるまで待つ

だから、これは機能の一つが呼び出されるところである。

router.get('/playwall', account.checkSession, playwalls.get, function(req, res, next) { 
    res.render('dashboard/playwalls/index'); 
}); 

ユーザーがplaywalls.get機能火災、ログインしているかどうかをチェックした後。これは機能が現在どのように機能しているかです:

const playwalls = { 
    /* GET ALL PLAYWALLS FOR THAT USER, FOR ADMIN GET THEM ALL 
    -------------------------------------------------------------- */ 
    get(req, res, next) { 
    req.session.playwalls = []; 
    const dataCollection = db.collection('data'); 
    const data = dataCollection.find({}); 
    console.log(typeof data) 
    const today = new Date(); 
    data.forEach(function(d) { 
     console.log(data.length) 
     if(d.admin == req.session.userData.username || req.session.userData.role == 'admin') { 
     const expireDate = new Date(d.date); 
     if(expireDate < today && d.status == 'actief') { 
      playwalls.editStatus(d, req, res, next); 
     } 
     req.session.playwalls.push(d); 
     } 
    }) 
    setTimeout(function() { 
     next(); 
    }, 1000) 
    }, 
    // Here the rest of the methods 
} 

私の質問は、 data.forEachループがクエリによって返されたすべてのドキュメントを処理した場合にのみ、next()関数が起動されることを確認するにはどうすればよいですか?だから私はsetTimeout()機能を取り除くことができます。

私の質問は明確で誰かが私を助けることを願っています。私はインターネット上を見回しましたが、適切な答えを見つけることができませんでした。

ありがとうございます!

+1

あなたは使えます – Mekicha

+1

約束通りに実行する必要があるコードをラップすることができます。私。 forEachを約束を返す別の関数に入れ、現在位置している場所でそれを解決し、次に呼び出す – bazzells

+1

'promises'を使うべきです。しかし、コールバックのために 'async'ライブラリを見ることもできます – sidgate

答えて

1

あなたを反復処理することができるようにあなたは、Cursor.toArrayを使用する必要がありますあなたはforEachコールバック内のいくつかの非同期仕事をする必要がある場合は、同期の方法で文書が、あなたはPromise

を使用することができます0
const playwalls = { 
    /* GET ALL PLAYWALLS FOR THAT USER, FOR ADMIN GET THEM ALL 
    -------------------------------------------------------------- */ 
    get(req, res, next) { 
     req.session.playwalls = []; 
     const dataCollection = db.collection('data'); 
     const data = dataCollection.find({}); 
     console.log(typeof data) 
     const today = new Date(); 
     data.toArray(function (err, documents) { 
      if (err) { 
       return next(err); 
      } 
      documents.forEach(function (d) { 
       console.log(data.length) 
       if (d.admin == req.session.userData.username || req.session.userData.role == 'admin') { 
        const expireDate = new Date(d.date); 
        if (expireDate < today && d.status == 'actief') { 
         playwalls.editStatus(d, req, res, next); 
        } 
        req.session.playwalls.push(d); 
       } 
      }) 
      next(); 
     }) 
    }, // Here the rest of the methods 
} 
+0

は、このまだタイミングの問題を引き起こすのでしょうか? – bazzells

+0

これがexpressjsの次のコールバックであれば、それはループで渡されるべきではありません –

1

promiseを返す関数の定義はどうですか?だから、

、別の関数に出forEachを引っ張っ:あなたのforEachの代わりに関数を起動すると

function promisedForEach(data) { 
    return new Promise(resolve => { 
     // your code 
     resolve('ready') 
    } 
} 

promisedForEach(data).then(/* carry on */) 
0

私はすべてが同じスレッドで起こらなければならないので、setTimeoutは動作しないと思います。だから、setTimeoutは実行されるべきときに単にフリーズします。

もう1つの方法は、rxjsオブザーバを使用することです。 https://github.com/ReactiveX/RxJSこれは、ページをレンダリングする前に、ミドルウェアなどのアプリケーションの他の部分にあるものを待つ場合に便利です。

次のようなことができます。私はこれをテストしていない。私はあなたにちょっとしたアイデアを伝えます。

global.Rx = require('rxjs/Rx'); 

router.get('/playwall', function(req, res) { 
    const myProcesses = { 
    ready: new Rx.Subject(false), 
    loading: false, 
    readiness: { 
     process1: { 
     ready: false 
     }, 
     process2: { 
     ready: false 
     }, 
     process3: { 
     ready: false 
     } 
    }, 
    checkReadiness: function(){ 
     if (
     this.readiness.process1==true 
     && this.readiness.process2==true 
     && this.readiness.process3==true 
    ) { 
     this.loading = false; 
     this.ready.next(true); 
     } 
    }, 
    }; 
    //asynchronous process 
    (function(){ 
    anObject.fetchAll().then(function (results){ 
     myProcesses.readiness.process1 = true; 
     myProcesses.checkReadiness(); 
    }) 
    })(); 

    //another asynchronous process 
    (function(){ 
    anObject2.fetchAll().then(function (results){ 
     myProcesses.readiness.process2 = true; 
     myProcesses.checkReadiness(); 
    }) 
    })(); 

    //another asynchronous process 
    (function(){ 
    anObject2.fetchAll().then(function (results){ 
     myProcesses.readiness.process3 = true; 
     myProcesses.checkReadiness(); 
    }) 
    })(); 

    //When all asynchronous processes have been completed 
    myProcesses.ready.subscribe({next: (v) => { 
    if (v==true){ 
     res.render('ejs/products/checkout', {}); 
    } 
    }}); 
}); 
関連する問題