2017-05-29 127 views
-3

我知道這是一個有很多信息的話題,但我仍然無法解決這個問題。我有一個數組,我需要迭代數組,並做一些與數據的東西,事情是我需要做一個查詢到MySQL服務器,但我需要for循環等待,直到我得到了查詢的結果,我已經嘗試了很多東西,現在我正在嘗試使用.each方法的藍鳥,但仍然無法正常工作,這是我的代碼。循環內的異步承諾

最初的功能是Notification.getByUser

在此先感謝

'use strict'; 
 
var Promise = require("bluebird"); 
 

 
module.exports = function(Notifications) { 
 
    Notifications.execute = function(sql, itemId) { 
 
    return new Promise((resolve, reject) => { 
 
     this.dataSource.connector.execute(sql, (e, result) => { 
 
     console.log('-----RESULT----', itemId); 
 
     console.log(result); 
 
     console.log('-----ERROR-----', itemId); 
 
     console.log(e); 
 
     if (result.length === 0) { 
 
      resolve(false); 
 
     } else { 
 
      resolve(true); 
 
     } 
 
     }); 
 
    }); 
 
    }; 
 
    Notifications.isMatching = function(item, user, type) { 
 
    return new Promise((resolve, reject) => { 
 
     console.log(type, item, user); 
 
     if (item !== null) { 
 
     if (item !== user) { 
 
      resolve(false); 
 
     } 
 
     } 
 

 
     resolve(true); 
 
    }); 
 
    }; 
 
    Notifications.getByUser = function(userId, isZolver, countryId, cityId, userState, cb) { 
 
    var where = { status: 1 }; 
 
    var plainText = ''; 
 
    var items = Notifications.find({ where }); 
 
    Promise.each(items, item => { 
 
     return Notifications.isMatching(item.isZolver, isZolver, 'isZolver') 
 
     .then(() => { 
 
      Notifications.isMatching(item.cityId, cityId, 'cityId'); 
 
     }) 
 
      .then(() => { 
 
      if(item.extraCondition !== null && item.extraCondition !== '') { 
 
       var sql = item.extraCondition.replace(/:user_id/g, userId); 
 
       // console.log(sql); 
 
       Notifications.execute(sql, item.id) 
 
       .then(render => console.log('extraCondition', render)); 
 
      } else { 
 
       console.log('extraCondition', true); 
 
      } 
 
      }); 
 
    }).then(res => { 
 
     // console.log('res del loop', res); 
 
    }); 
 
    cb(null, 'ok'); 
 
    }; 
 
};

+2

你'.then'調用必須返回的東西('返回Notifications.execute(sql','返回Notifications.isMatching' ...) 。你的'isMatching'函數不是異步的,也許你可以簡化你的代碼 – arvymetal

+1

這段代碼有太多的錯誤:你應該首先解決一個更簡單的算法,學習使用promise(而不是在最後使用同步回調來混合它們,它只是使用promises ...完全無用) – trincot

+0

您可以通過nsynjs以同步方式運行您的代碼,請參閱https://github.com/amaksr/nsynjs/tree/master/examples/node-mysql,例如順序語句執行。 – amaksr

回答

0

有幾個問題與您的代碼:

  • 爲了鏈承諾,你必須一定要回報你一個then回調

  • 你不應該需要創建結果立即可用的(isMatching

  • 當承諾履行始終執行的then回調承諾中創建一個承諾。無論您是否做resolve(false):即使承諾值爲false,這仍會使承諾完成並觸發then回撥。

有在你的代碼中的一些未知因素,如Notifications.find,什麼樣的SQL您要執行的:它返回結果集,如果是的話,你會不會有興趣得到這一結果,而不是僅僅解決到布爾?

無論如何,這裏有一些應用更正:

'use strict'; 
var Promise = require("bluebird"); 

module.exports = function(Notifications) { 
    Notifications.execute = function(sql, itemId) { 
     return new Promise((resolve, reject) => { 
      this.dataSource.connector.execute(sql, (e, result) => { 
       console.log('-----RESULT----', itemId); 
       console.log(result); 
       console.log('-----ERROR-----', itemId); 
       console.log(e); 
       resolve (result.length !== 0); // The `if ... else` is overkill 
      }); 
     }); 
    }; 

    //You don't need isMatching to return a promise 
    Notifications.isMatching = function(a, b) { 
     return a === null || a === b; 
    }; 

    Notifications.getByUser = function(userId, isZolver, countryId, cityId, userState) { 
     var where = { status: 1 }; 
     var items = Notifications.find({ where }) 
      // use filter() to limit the items to those you want to execute the SQL for 
      .filter(item => { 
       return Notifications.isMatching(item.isZolver, isZolver) 
        && Notifications.isMatching(item.cityId, cityId) 
        && item.extraCondition !== '' 
      }); 
     // Return the promise! (don't go back to the old callback system!) 
     return Promise.each(items, item => { 
      var sql = item.extraCondition.replace(/:user_id/g, userId); 
      // Return the promise! 
      return Notifications.execute(sql, item.id); 
     }).then(res => { 
      console.log('res del loop', res); 
     }); 
    }; 
}; 

注意的Notifications.getByUser簽名不具有最終的回調參數:一旦你開始使用他們,你應該繼續使用的承諾,所以,當你調用這個函數,調用結果的then方法,就像您對任何承諾做到:

Notifications.getByUser(.......arguments....).then(function() { 
    // do something... 
}); 
+0

你的回答很棒,非常感謝,我是PHP的逃兵,JavaScript有時有點複雜但有趣,對我來說這是一個全新的世界:) – Grunch

+0

不客氣;-) – trincot