Определение области видимости узла JS

#javascript #node.js #scope

#javascript #node.js #область видимости

Вопрос:

Что-то не так с моей областью видимости, которую я здесь не совсем понимаю. У меня есть следующий пример кода:

 /**
 * Created by David on 10/9/2016.
 */
var public = {};

//REQUIRES
var fs = require('fs');
var rl = require('readline');

//========================================
var configFile = './config';
public.configFile = configFile;

//========================================
public.readSettingsFile = function(conFile){
    return new Promise(function(resolve,reject){
        try {
            console.log("Importing Settings");
            //read configuration file line by line
            var lineStream = rl.createInterface({
                input: fs.createReadStream(conFile === undefined ? configFile : conFile)
            });
            lineStream.on('line', function (line) {
                if(!line.startsWith('#')){
                    var splitLine = line.split('=');
                    switch(splitLine[0]){
                        case 'version':
                            public.version = splitLine[1];
                        break;
                        case 'basePath':
                            public.basePath = splitLine[1];
                        break;
                    }

                }
                resolve(public);
            });

        }catch(err){
            reject(err);
        }
    });
}

//========================================

module.exports = public;
 

Я ожидал бы, что с обещаниями, что в файле .then p должен вернуться после успешного чтения установочного файла, этот public.version теперь должен быть включен, но он возвращает следующее:

 { configFile: './config', readSettingsFile: [Function] }
 

Консоль.войдите в систему, оператор switch правильно возвращает:

 0.1
 

Комментарии:

1. Вы даже не вызвали public.readSettingsFile функцию. Когда вы это сделаете, вы обнаружите, что ваш код readline является асинхронным.

2. Многое из того, что вы делаете, неясно и неполно. Где вы на самом деле вызываете файл readSettingsFile, например? Ваше обещание также не возвращает результат в случае успеха.

3. Извините, отредактировано, чтобы попытаться придать ему больше смысла

4. @zerkms, мне интересно, учитывая то, как я настроил обещание, оно все еще действует асинхронно, поэтому возвращает действительное обещание, несмотря на то, что я не закончил чтение?

5. new Promise(function(resolve,reject){ reject(err); }); просто Promise.reject(err) .

Ответ №1:

Я думаю, что ваша проблема не в «области видимости», но вы не понимаете, как использовать обещания. Я настоятельно рекомендую как документацию Mozilla, так и сообщение в блоге Дэвида Уолша. Я также рекомендую вам начать с малого и написать несколько простых обещаний, прежде чем пробовать что-то более сложное.

Теперь я отвечу на ваш конкретный вопрос. Причина, по которой вы не видите того, что хотите видеть, заключается в том, что весь ваш бизнес linestream является асинхронным. Вы возвращаете обещание в конце своей функции, прежде чем перейти к оператору switch. В принципе, думайте о promise как о целой функции. Но вместо того, чтобы возвращать значение, вы возвращаете обещание значения или ошибки. Если вы вводите обещание в середине функции, ваша функция пытается сделать слишком много вещей, и вам нужно больше отделять свой код.

Это должно быть ближе к тому, что вы хотите. Это не идеальный код, и он может не соответствовать вашим потребностям, но, надеюсь, он поможет вам на правильном пути. Удачи.

 public.readSettingsFile = function(conFile){
    return new Promise(function(resolve, reject) {
        var lineStream = rl.createInterface({
            input: fs.createReadStream(conFile === undefined ? configFile : conFile)
        });
        lineStream.on('line', function (line) {
            if(!line.startsWith('#')){
                var splitLine = line.split('=');
                // You don't need a switch statement for only one case
                if (splitLine[0] === 'version') {
                        public.version = splitLine[1];
                        console.log(public.version);
                        // You actually have to resolve something
                        resolve(public);
                } else {
                // There's a problem, reject it.
                reject("Some error message");
            }
        });
    }
} 
 

Ответ №2:

Код, который у меня был, на самом деле был в основном правильным, но, как упомянул Пол в своем ответе, решение было в неправильном месте. lineStream.on выполнялся асинхронно, и разрешение находилось за пределами его завершения, поэтому он выполнял путь «разрешения» без фактического правильного завершения.