1

Есть такая проблема: стандартный сервер http.createServer()..listen();, внутри него идёт обработка того, что получено разными методами. В одном из случаев мы кидаем данные во внешнюю функцию, внутри которой подключаемся к LDAP и через асинхронный метод search.on() получаем ответ. Вопрос в том, как вернуть ответ клиенту????

Приблизительный код:

http.createServer(function (req, res) {
    if (req.method !== undefined && (req.method).toString() === "POST") {
        var body = '';
        req.on('data', function (data) {
            body += data;
        });
        req.on('end', function () {
            var body_arr = decodeURIComponent(body).replace(/[+]/g, " ").replace(/[^А-ЯЁа-яё0-9=]/gi, "").split('=');
            res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
            res.end(LDAP_search(pbdb, body_arr[0], body_arr[1]));
        });
    }
}).listen("8088");


function LDAP_search(attribute_id, search_str) {
    var ldap_user = 'user';
    var ldap_pass = 'pass';
    var ret_array = [];
    var opts = {
        filter: "(&(" + attribute_id + "=" + search_str + "*))",
        scope: "sub"
    };
    client.bind(ldap_user, ldap_pass, function (err, res) {
        if (err) {
            console.log("ERROR: bind error" + err);
        }
        client.search('DC=mydomain,DC=ru', opts, function (err, search) {
            search.on('searchEntry', function (entry) {
                var tem_json_obj = {};
                tem_json_obj.sn = entry.object.sn || "";
                ret_array.push(tem_json_obj);
            });
            search.on('end', function (err) {
                client.unbind(function (err, data) {
                    if (err) {
                        console.log(err);
                    } else {
                        console.log(ret_array);
                    }
                });
            });
        });
    });
}
Dmi7ry
  • 782

1 Answers1

3

Отсылка ответа клиенту продолжается до вызова end(), поэтому не должна вызывать проблем сама по себе.

Вместо ожидания завершения обращения в LDAP, надо в соответствующую функцию передать коллбек, который она вызовет сама, когда получит нужные данные (и передаст ему вторым аргументом - первым принято передавать ошибку или null, если всё хорошо).

Коллбек делает с полученными данными всё что требуется и уже из него завершается ответ на запрос.


Наконец-то код в вопросе появился.

function LDAP_search(attribute_id, search_str) {

Этот метод переделай так:

function LDAP_search(attribute_id, search_str, callback) {
client.unbind(function (err, data) {
  if (err) {
    console.log(err);
  } else {
    console.log(ret_array);
  }
});

А в этом куске вместо вывода на консоль вызывай коллбек с обоими параметрами.
Ну и функцией выше при ошибке - тоже надо коллбек вызывать.


В итоге должно получиться что-то примерно такое:

http.createServer(function (req, res) {
    if (req.method !== undefined && (req.method).toString() === "POST") {
        var body = '';
        req.on('data', function (data) {
            body += data;
        });
        req.on('end', function () {
            var body_arr = decodeURIComponent(body).replace(/[+]/g, " ").replace(/[^А-ЯЁа-яё0-9=]/gi, "").split('=');
            res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
            LDAP_search(pbdb, body_arr[0], body_arr[1], function (err, data) {
              if (err) throw err;
              res.end(data);
            });
        });
    }
}).listen("8088");

function LDAP_search(attribute_id, search_str, callback) {
    var ldap_user = 'user';
    var ldap_pass = 'pass';
    var ret_array = [];
    var opts = {
        filter: "(&(" + attribute_id + "=" + search_str + "*))",
        scope: "sub"
    };
    client.bind(ldap_user, ldap_pass, function (err, res) {
        if (err) {
            callback(err, null);
            return;
        }

        client.search('DC=mydomain,DC=ru', opts, function (err, search) {
            if (err) {
                callback(err, null);
                return;
            }

            search.on('searchEntry', function (entry) {
                var tem_json_obj = {};
                tem_json_obj.sn = entry.object.sn || "";
                ret_array.push(tem_json_obj);
            });

            search.on('end', function (err) {
                client.unbind(function (err, data) {
                    callback(err, ret_array)
                });
            });
        });
    });
}
Qwertiy
  • 123,725
  • проблема в том что мне нужно ответить на AJAX запрос, то есть из тела createServer() вызывается ф-ция поиска по LDAP , в которой уже вложена асинхронная ф-ция bind() внутри которой асинхронная ф-ция поиска из которой надо вернуть ответ на AJAX запрос, и я не понимаю как это сростить без костылей –  Jun 18 '15 at 12:40
  • @vnn198, не понимаю, где там могут быть костыли. Ajax'ность запроса вообще никак не влияет на ответ. – Qwertiy Jun 18 '15 at 13:33
  • Я просто непонимаю как мне вернуть ответ от ф-ции поиска которая делает ответ через вложенную асинхронную ф-цию ps : на самом деле эта асинхронная хрень в Node очень бесит. чтобы сделать элементарную вещь нужно придумывать карбоновые нано костыли –  Jun 18 '15 at 14:22
  • @vnn198, не надо возвращать. Она должна вызвать коллбек сама. Вторая вложенная. – Qwertiy Jun 18 '15 at 14:36
  • ну вызовет и что этот калбек будет делать??? как он вернёт ответ функции вызвавшей поиск –  Jun 18 '15 at 14:46
  • @vnn198, этот колбек и пошлёт ответ на запрос!!! – Qwertiy Jun 18 '15 at 15:03
  • @vnn198, дополнил ответ с учётом кода. – Qwertiy Jun 18 '15 at 15:08
  • непонимаю логику работы это структуры –  Jun 18 '15 at 15:22
  • @vnn198, и что же непонятно?? – Qwertiy Jun 18 '15 at 15:28
  • что за аргумент callback, и как вызывать его чтобы вернуть данные в вызвавшую его функцию –  Jun 18 '15 at 15:36
  • @vnn198, коллбек - это функция. Вызвать как функцию. Погугли наконец! – Qwertiy Jun 18 '15 at 15:44
  • вот кажется я нашел более-менее внятное объяснение как это использовать –  Jun 18 '15 at 20:17
  • вобщем непонятно как это может мне помочь, в гугле ничего толкового тоже нет –  Jun 29 '15 at 13:51
  • @vnn198, http://learn.javascript.ru/nodejs-screencast - посморти и разберись. – Qwertiy Jun 29 '15 at 14:09
  • там нет ответа на мой вопрос –  Jun 29 '15 at 14:18
  • @vnn198, на твой вопрос я уже ответил. Тебе осталось только понять, что такое асинхронные операции и коллбеки, и как ими пользоваться. – Qwertiy Jun 29 '15 at 14:35
  • в том то и дело что ответа толком небыло, ну получаю я ещё один калбек, а как мне его связать с ф-цией которая его вызвала –  Jun 29 '15 at 14:37
  • @vnn198, через замыкание же. Дополнил ответ. – Qwertiy Jun 29 '15 at 14:41
  • @vnn198, получилось наконец-то? – Qwertiy Jun 30 '15 at 13:30
  • пока до конца нет, почему-то сервер не закрывает соеденение и браузер чего-то ждёт, но в целом работает и в браузере ответ есть, что уже хорошо :) так что спасибо за ответ –  Jun 30 '15 at 20:27