Функция не может вернуть значение

Итак, я делаю простой инструмент стеганографии (шифрование сообщений внутри изображений) и представляю его как веб-сервис через Node.js. Я очень новичок в Javascript и Node.js в частности. Приложение сначала преобразует текстовую строку в двоичную строку, превращая каждый символ в 8-битную кодировку ASCII, в результате чего получается одна большая двоичная строка. Затем я шифрую сообщение в пикселях. Четные значения пикселей представляют 0 из двоичного кода, а нечетные значения представляют 1 с. Конец строки помечен как 3 пикселя со значением 100 подряд (это временно, пока я не найду лучший способ отметить конец). Я использую библиотеку node.js под названием «pngjs», которая дает мне доступ к изображениям png на уровне пикселей.

Итак, у меня проблема с функцией decodeMessage. Он создает строковое сообщение и затем предназначен для его возврата, однако обратный вызов в конце приводит к неопределенности.

Как я могу это исправить?

Заранее спасибо за помощь!

function encodeMessage(image, mes) {

    var message = mes;

    var fs = require('fs'),
    PNG = require('pngjs').PNG;

    fs.createReadStream(image)
    .pipe(new PNG({
        filterType: 4
    }))
    .on('parsed', function() {

        for (var y = 0; y < this.height; y++) {
            for (var x = 0; x < this.width; x++) {
                var idx = (this.width * y + x);// << 2;
                //console.log(idx); 
                if (idx < message.length) {

                    var item = message.charAt(idx);

                    /* if the character in the encoded string is 0 */
                    if (item == 0) {
                        /* if the pixel is odd, we want it to be even */
                        if (this.data[idx] % 2 == 1) {
                        /* if the pixel is 0, add 1 to it */
                        if (this.data[idx] == 0) {
                            this.data[idx] = this.data[idx] + 1;
                        } else {
                            /* else substract 1 */
                            this.data[idx] = this.data[idx] - 1;
                        }
                        }
                    } else {
                        /* if the character in the encoded string is 1 */
                        if (this.data[idx] % 2 == 0) {
                        if (this.data[idx] == 0) {
                            this.data[idx] = this.data[idx] + 1;
                        } else {
                            this.data[idx] = this.data[idx] - 1;
                        }
                        }
                    }

                    //console.log(this.data[idx]);

                } else if (idx === message.length) {

                    /* do something to the first pixel following the end of the string */
                    this.data[idx] = 100;
                    this.data[idx+1] = 100;
                    this.data[idx+2] = 100;
                    //console.log(this.data[idx]);

                } else {

                    /* do something to the remaining pixels */

                }                  
            }
        }
        this.pack().pipe(fs.createWriteStream('encoded_' + image));
    });
}

function decodeMessage(image) {
    var message = "";

    var fs = require('fs'),
    PNG = require('pngjs').PNG;

    fs.createReadStream(image)
    .pipe(new PNG({
        filterType: 4
    }))
    .on('parsed', function() {


        dance:
        for (var y = 0; y < this.height; y++) {
            for (var x = 0; x < this.width; x++) {

                var idx = (this.width * y + x);// << 2;

                if (this.data[idx] == 100 && this.data[idx+1] == 100 && this.data[idx+2] == 100) {
                    break dance;
                } else {

                    if (this.data[idx] % 2 == 0) {
                        message += "0";
                    } else {
                        message += "1";
                    }

                }

            }
        }
        /* the message outputs correctly over here */
        console.log(message);
        //return message;
    });

    /* but the return of the variable here doesn't work */
    return message;
}

exports.encodeMessage = encodeMessage;
exports.decodeMessage = decodeMessage;

person Dinislam Tebuev    schedule 19.03.2013    source источник
comment
Добро пожаловать в удивительный мир async! Вы не можете этого сделать.   -  person SLaks    schedule 19.03.2013


Ответы (1)


Событие parsed запускается асинхронно, поэтому вы не можете вернуть значение из decodeMessage.

function decodeMessage(image, cb) {

  // Code
  .on('parsed', function() {
    // Code

    console.log(message);
    cb(message);
  });
}

Затем вы должны передать обратный вызов вашей функции decodeMessage.

decodeMessage(image, function(decoded){
  // Here is the decoded data.
});

То же самое верно и для вашей функции encodeMessage. Функция вернется до завершения кодирования. Если вы хотите знать, когда это будет сделано, вам нужно передать обратный вызов таким же образом.

person loganfsmyth    schedule 19.03.2013
comment
Спасибо! Теперь я понимаю концепции асинхронных функций. Я все еще пытаюсь заставить функцию возвращать строку «сообщение». Функции в этом модуле .js экспортируются в другой модуль и вызываются там. Мне нужно вернуть строку «сообщение» во внешнюю переменную. Как я могу этого добиться? - person Dinislam Tebuev; 20.03.2013
comment
@DinislamTebuev Нет проблем! Проблема в том, что поскольку он асинхронный, вы не можете вернуть ничего полезного. Вместо этого вам нужно передать обратный вызов и сделать любой код, который вызывает decodeMessage, также асинхронным. Асинхронность является вирусной в том смысле, что если вы хотите вызывать что-то асинхронное, то для правильного его использования вам также нужно сделать весь свой собственный код асинхронным. Если вы используете функции модуля, я могу добавить больше примеров. - person loganfsmyth; 20.03.2013
comment
Было бы здорово! Я разбиваю свой код на модули, чтобы следовать хорошему стилю программирования. Мой файл server.js будет вызывать эти функции, и он должен обрабатывать несколько запросов одновременно, поэтому, как я понимаю, все должно быть асинхронным. - person Dinislam Tebuev; 20.03.2013
comment
В основном вы хотите вызвать функцию и передать обратный вызов, как мой второй фрагмент. - person loganfsmyth; 20.03.2013