Обещайте объркване при използване на възел (ES6) и Bluebird

Имах проблем с присвояването на стойности преди завършването на асинхронно извикване, така че избрах да използвам Promises (в този случай: Bluebird). Което мислех, че ще реши проблема, но тъй като изобщо не съм запознат с обещания / или възел за този въпрос, той все още прави същото.

Как да променя кода си по-долу, за да използвам обещанията правилно? И да поддържам поток, така че да мога да валидирам modules въз основа на предишен row?

var Promise         = require('bluebird');
var db              = require('../shared/db');
var queryHelper     = require('../shared/queryHelper');
var schemas         = require('../schemas/schemas');
var _               = require('lodash');
var serverSettings  = require('../shared/coreServerSettings');

// Create new instance of mysql module
var connection      = new db();
var queryhelper     = new queryHelper();

// Promised methods
var queryAndWait = Promise.promisify(connection.query);

..изрезка..

queryAndWait(query + '; ' + queryFoundRows, params).then(function (result) {
  var payload = [];
  var site_access = [];
  var module_access = [];

  _.each(result[0], function (row) {
    var sites = row.site_access.split(',');
    _.each(sites, function (site_id) {
      site_access.push(site_id);
    });

    row.site_access = site_access;
    site_access = [];

    queryAndWait(queryModules, [row.priv_id]).then(function (result) {
      _.each(result, function (module) {
        var modulePriv = {
          priv_name: module.priv_name,
          priv_num: module.priv_num,
          enabled: module.enabled
        };

        module_access.push(modulePriv);
      });

      //console.log("am assigning " + JSON.stringify(module_access));
      row.module_access = module_access;
      module_access = []
    });

    payload.push(row);
  });
});

Да се ​​изяснят:

За съжаление, модулите са групи от продукти, до които потребителите (ред) имат достъп, които се изчисляват в движение (побитово - следователно няма налично присъединяване и отделна заявка), заявката за модул връща нещо като следното, което след това преминавам през и прикрепете към реда преди връщане на полезния товар:

[{"priv_name":"INTERACT","priv_num":1,"enabled":1},{"priv_name":"STAFF_ADMIN","priv_num":32,"enabled":1},{"priv_name":"INT_EDIT","priv_num":64,"enabled":0},{"priv_name":"FAILED_LOGIN","priv_num":128,"enabled":0},{"priv_name":"INT_TAGS","priv_num":256,"enabled":0},{"priv_name":"NC","priv_num":512,"enabled":0},{"priv_name":"CC_TIMETABLE_MGR","priv_num":1024,"enabled":0}]

person fantasitcalbeastly    schedule 23.09.2015    source източник
comment
Какво е modules и какъв е очакваният резултат?   -  person thefourtheye    schedule 23.09.2015
comment
Актуализирах, за да изясня   -  person fantasitcalbeastly    schedule 23.09.2015
comment
Само странична бележка, всички функции на lodash, които използвате тук, са внедрени в JavaScript, няма нужда от библиотека.   -  person baao    schedule 23.09.2015


Отговори (2)


да, вътрешният queryAndWait ще работи независимо за всеки ред, тъй като не свързвате обещанията.

Тъй като използвате bluebird, ще ви трябва нещо подобно, за да поддържате потока

queryAndWait(query + '; ' + queryFoundRows, params).then(function (result) {
    return Promise.map(result[0], function (row) {
        var site_access = [];
        var module_access = [];

        var sites = row.site_access.split(',');
        _.each(sites, function (site_id) {
            site_access.push(site_id);
        });

        row.site_access = site_access;

        return queryAndWait(queryModules, [row.priv_id]).then(function (result) {
            _.each(result, function (module) {
                var modulePriv = {
                    priv_name: module.priv_name,
                    priv_num: module.priv_num,
                    enabled: module.enabled
                };

                module_access.push(modulePriv);
            });
            row.module_access = module_access;
            return row;
        });
    });
}).then(function(payload) {
    console.log(payload);
}).catch(function(error) {
    console.log(error);
});
person code-jaff    schedule 23.09.2015
comment
row.site_access = row.site_access.split(',');. Не е необходимо четене в друг масив. - person Roamer-1888; 23.09.2015

Promise ви помага да контролирате потока на приложението по лесен начин. Препоръчвам ви да прочетете основните принципи относно обещанието, поне спецификацията на Promise A+.

Вашият код може да бъде написан по много начини, това е начинът, който препоръчвам, защото е модулен:

var Promise         = require('bluebird');
var queryAndWait = Promise.promisify(connection.query);

function getRows(params) {
  return queryAndWait(query + '; ' + queryFoundRows, params)
          .then(function (result) {
            var site_access = [];
            _.each(result[0], function (row) {
              var sites = row.site_access.split(',');
              _.each(sites, function (site_id) {
                site_access.push(site_id);
              });
              row.site_access = site_access;
              site_access = [];
              return row;
            });
          });
}


function getModules(row) {
 return queryAndWait(queryModules, [row.priv_id])
         .then(function (result) {
          var payload = [];
          var module_access = [];
          _.each(result, function (module) {
            var modulePriv = {
              priv_name: module.priv_name,
              priv_num: module.priv_num,
              enabled: module.enabled
            };

            module_access.push(modulePriv);
          });              
          row.module_access = module_access;

          payload.push(row);
          return payload;
        });
}

getRows(params)
  .then(getModules)
  .then(function(payload) {
    // Do something with your payload
  })

Направих следното:

  1. Отделете всяка логика в нейната собствена функция (Защо?, Защото можете да използвате повторно логиката в друго обещание, експортирате методи в други библиотеки и т.н.)
  2. Връщам обещанието във всяка функция. Обещанието може да бъде вложено и да се изпълнява по ред.
  3. Всяко стажантско обещание разрешава стойност. getRows -> разрешаване на редове, getModules -> разрешаване на полезен товар

Можете също така да управлявате грешките, като използвате catch метода на promises, например:

getRows(params)
  .catch(function(err) {
    // Something went wrong with getRows
    // If i can't recovery must return a reject.
  })
  .then(getModules)
  .catch(function(err) {
    //Something went wrong with getModules
    // If i can't recovery must return a reject.
  })
  .then(function(payload) {
    // Do something with your payload
  })
person Jesús Quintana    schedule 23.09.2015