2017-09-27 72 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 
} 

我的問題是;我如何確保next()函數僅在data.forEach循環已處理查詢返回的所有文檔時纔會觸發?所以我可以擺脫setTimeout()的功能。

希望我的問題很清楚,有人可以幫助我。我在網上瀏覽過,但找不到合適的答案。

在此先感謝!

+1

你可以用'promise's – Mekicha

+1

你可以換你需要有完成的承諾執行代碼。即將forEach放入一個單獨的函數,返回一個promise,然後將其解析到當前所在的位置,然後調用 – bazzells

+1

u應該開始使用'promises'。但你也可以看'異步'庫回調 – sidgate

回答

1

你應該使用Cursor.toArray,這樣你就可以遍歷您文件同步方式,那麼如果你需要在forEach裏面做一些異步作業回調,你可以使用Promise

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

當playwalls.editStatus被調用時,這仍然會導致計時問題嗎? – bazzells

+0

如果這是expressjs next回調,它不應該循環傳遞 –

1

如何定義返回promise的函數?

所以,拉forEach到一個單獨的功能:

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

然後調用函數來代替你的foreach:

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

我不認爲setTimeout將工作,因爲一切都必須發生在同一個線程。所以setTimeout只是簡單地凍結在輪到被執行時。

另一種方法是使用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', {}); 
    } 
    }}); 
}); 
相關問題