Ответы пользователя по тегу Node.js
  • Can't set headers after they are sent?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    думаю проблема тут:
    fs.writeFile(fullPath, base64Image, { encoding: 'base64' }, err => {
                if (err) return res.status(500).send(`Ошибка сохранения файла: ${err}`)
                else return
            });


    так как после этого куска кода не дожидаясь результата выполняется следом идущий код. Таким образом возможна ситуация, при которой send в этом куске кода выполнится уже после send-а в последующем коде

    попробуйте заменить этот код на:
    const promise = new Promise(resolve, reject)=>{
       fs.writeFile(fullPath, base64Image, { encoding: 'base64' }, err => {
          if (!err) return resolve(true);
          
          res.status(500).send(`Ошибка сохранения файла: ${err}`)
          return reject(false);
       });
    });
    const isWrite = await promise;
    if(!isWrite) return;
    Ответ написан
    2 комментария
  • Как правильно создать новый файл в NodeJS?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    сначала создай директории в которых это файл лежит

    если версия ноды больше чем 10.12.00 то попробуйте так

    function saveFileSync(path, data){
      let list = path.split(/[\\\/]/);
      let filename = list.pop();
      let filepath = list.join('/');
      fs.mkdirSync(filepath, { recursive: true }, (err) => {
        if (err) throw err;
      });
      fs.writeFileSync(path, data);
    }
    
    
    
    let date = new Date();
    let filename = SSN + '_' + date.getFullYear() + '/' + date.getMonth() + '/' + date.getDay() + '_' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds() + '.txt';
    let text = ecg.join('');
    try{
        saveFileSync(filename, text);
    } catch (e) {
        console.log(e);
    }
    Ответ написан
  • Почему теряется контекст экземпляра класса?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Потому что он используется как мидлваре.
    Вызывайте его привязывая контент, както так

    const Authorized = require('../moduls/authorized')
    const auth = new Authorized();
    
    
    // так
    router.get("path/",auth.isAuthorized.bind(auth));
    // или так
    router.get("path/",(...a)=>auth.isAuthorized(...a));

    и еще кучей способов

    вот, можете почитать про Привязка контекста к функции

    а еще лучше измените метод isAuthorized примерно так:
    isAuthorized(){
       return (req, res, next)=>{
          console.log('isAuth',this)
          // тут код мидлвара
      }
    }


    и используйте его так
    router.get("path/",auth.isAuthorized());
    // или
    router.post("path/",auth.isAuthorized());
    // или
    router.use(auth.isAuthorized());
    Ответ написан
    1 комментарий
  • Как создать сессию?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    как показано в описании client-sessions помимо опции secret надо задать еще ряд опций, таких как cookieName (она же имя сессии) либо requestKey (requestKey overrides cookieName for the key name added to the request object).
    что позволит обращаться к сесcии через req

    ваш пример с исправлениями ошибок
    const express = require('express'),
        app = express(),
        port = 3000,
        clientSessions = require('client-sessions');
    
    app.use(clientSessions({
        secret: '0GBlJZ9EKBt2Zbi2flRPvztczCewBxXK', // set this to a long random string!
        cookieName: 'ss', // cookie name dictates the key name added to the request object
        requestKey: 'session', // requestKey overrides cookieName for the key name added to the request object.
    }));
    
    app.get('/',(request,response,next) => {
        request.session.username = 'qwer';
        response.send("вы обратились к /");
    });
    
    app.get('/1',(request,response,next) => {
        console.log(request.session.username);
        response.send("вы обратились к /1<br>в сессии сохранено: "+JSON.stringify(request.session));
    });
    
    app.listen(port,(err) => {
        if(err){
            return console.log(err);
        }
    
        console.log(`Слушается порт ${port}`);
    });


    PS: и не забывайте вызывать next(); там где требуется передать управление следующему обработчику или же request.end() или request.send(...) там где требуется прекратить дальнейшую обработку запроса

    PSPS: и пожалуйста, напишите в чем у вас возникли проблемы с ранее предложенным решением или отметьте его решением.
    Ответ написан
    Комментировать
  • Как вынесли переменную?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Никак не вынесите, но это и не нужно. Вот мой ответ (немного сумбурный) на по сути такой же вопрос. Посмотрите его.
    Как запомнить текст, который выполняется в функции?

    Вот вариант, позволяющий писать код как если бы он был синхронным.
    // так как name.names(...) асинхронный, то для того, чтобы получить 
    // результат запроса в "синхронном стиле" используем await
    
    // await можно использовать только внутри асинхронной функции.
    // для этой цели обернем блок с вызовами name.names(...) в
    // само вызывающуюся асинхронную функцию
    (async () => {
    
       var n = await name.names('text', { data });
       console.log(n);
    
    })()
    Ответ написан
    Комментировать
  • Как запомнить текст, который выполняется в функции?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Основная проблема в получении body заключена в том, что request асинхронный. То есть ответ придет не сразу, а через какое то время, при этом, js не будет дожидаться этого ответа а продолжит выполнять код, находящийся после request-а. Это в свою очередь приведет к тому, что в этом коде мы не можем получить ответ request-а, так происходит потому, что ответ еще не пришел)
    Как же быть в этой ситуации???
    Почитать про ассинхронность, промисы и async/await

    Далее привожу простенький класс, умеющий кэшировать ответы requesta, и пример его использования:
    тык сюда

    var request = require("request");
    
    
    // создаем класс для кэширования результатов запросов
    class СacheRequest {
    	// конструктор
    	constructor(handler){
    		// создаем ассоциативный массив для кэширования результата
    		this.cache = {};
    	}
    	
    	// основной метод класса, предназначен для получения данных по ссылке
    	// принимает url в качестве параметра
    	// возвращает выполненный промис если запрос есть в кэше
    	// или промис в ожидании выполнения запроса
    	async get(url){
    		// если такой запрос уже был, возвращаем промис с результатом из кэша
    		if( this.cache[url] )
    			return  Promise.resolve(this.cache[url]);
    		
    		// иначе возвращаем промис с ожиданием результата
    		return new Promise((resolve,reject)=>{
    			// делаем запрос на указаный url
    			request(url, (error, response, body)=>{
    				// если ошибка - реджектим )
    				if( error )
    					return reject(error);
    				
    				// иначе запоминаем в кэше ответ
    				this.cache[url] = body;
    
    				// и резолвим body
    				resolve(body);
    			});			
    		});
    	}
    
    	// метод отчищает кэш
    	clear(){
    		this.cache = {};
    	}
    }
    
    // создаем экземпляр кэша
    const cacheRequest = new СacheRequest();
    
    // так как request асинхронный, то для того, чтобы получить 
    // результат запроса в "синхронном стиле" используем await
    
    // await можно использовать только внутри асинхронной функции.
    // для этой цели обернем блок с вызовами cacheRequest.get в
    // само вызывающуюся асинхронную функцию
    (async () => {
    	// выполняем запросы:
    	// запросим "http://google.ru/" (будет сделан фактический запрос)
    	let body = await cacheRequest.get("http://google.ru/");
    	console.log("\n\n\nBODY:", body, 111);
    
    	// еще раз запросим "http://google.ru/" (будет взято из кэша)
    	body = await cacheRequest.get("http://google.ru/");
    	console.log("\n\n\nBODY:", body, 222);
    })()
    
    // раз в сутки отчищаем кэш
    setTimeout(()=>{
    	cacheRequest.clear();
    }, 1000*60*60*24 ); // 1000*60*60*24 это количество миллисекунд в сутках

    Ответ написан
    1 комментарий
  • Как подключить telegram бота в 2 файла?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    В tbot.js производите подключение бота и экспортируете уже подключенного бота (объект полученный при подключении бота)
    В остальных файлах require tbot и работаете уже с подключеным ботом.

    ЗЫ: но не забывайте, что все остальные файлы использующие бота должны запускаться в рамках одного процесса ноды.
    Если же вы будете их запускать по отдельности, это будет эквивалентно запуску нескольких экземпляров вашего бота и у вас опять все сломается.
    Есть несколько способов решения данной проблемы.
    1. Добавить в тбот прокси сервер на сокетах или вэбсокетах который будет содержать API на нужные вам функции бота. Далее из любого скрипта (в том числе и запущенного отдельно) подключаетесь к данному серверу и дергаете необходимые вам функции из API.
    2. Делаете 2х или более разных ботов (каждого со своим токеном)))
    3. Как писал выше, все файлы, использующие бота запускаете в рамках одного процесса, подключая их через require в главном файле проекта.

    ЗЫЗЫ: лично я делал бы по третьему варианту)
    Ответ написан
  • Где делать GET запрос в NodeJS или JS?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Если эти данные нужны только для отображения во фронте, делайте запрос во фронте
    Ответ написан
  • Как обрабатывать файлы не сервере правильно?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Как быть в случае, если путь до файла должен быть динамическим, например, по дням недели?

    Получая файл, в обработчике multer-а перемещаете файл в нужную вам папку (и переименовываете при необходимости). Это можно сделать как выполнив из ноды команду ОС (*nix, win), так и средствами самой ноды

    Выглядеть это будет примерно так:
    // роутер Express-а ./routes/files
    var fs = require('fs');
    var express = require('express');
    var router = express.Router();
    
    
    // получаем файлы
    var multer = require('multer');
    var upload = multer({ 
    	dest:'./folder_for_upload_files/'
    	// прочие опции
    }).single("upload");
    
    router.post('/files/upload', function(req, res, next) {
    	upload(req, res, function (err) {
    		if (err){
    		   // обработка ошибки
    		   // и завершение обработки запроса res.end() или res.send(...)
    		   return;
    		}
    		
    		// если же загрузка произошла успешно, то
    		// 1. определяем в какую папку и под каким именем переместить файл
    		// 2. перемещаем файл в нужную папку
    		// 3. делаем об этом запись в БД или в файлики или кудато еще (в место предназначенное для хранения этой информации)
    		// 4. завершаем обработки запроса ( res.end() или res.send(...) )
    		
    		// в помощь:
    		// req.file.originalname - оригинальное имя  файла на компе клиента
    		// req.file.filename - имя загруженного в "./folder_for_upload_files/" файла
    		
    		
    	});
    });
    
    
    module.exports = router;
    Ответ написан
    Комментировать
  • Как заставить все запросы ждать один промис?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Как подсказал Inviz Custos, очередь решит вашу проблему (если конечно правильно будет работать с дублирующими запросами и промисами)

    Вот простенький рабочий пример
    // внутри async function
    let quiz = global_quizzes[quiz_id];
    if(!quiz) {
        global_quizzes[quiz_id] = quiz = Chat_Quizzes.findById(quiz_id).exec();
    }
    
    if( quiz instanceof Promise ){
        global_quizzes[quiz_id] = quiz = await quiz;
    } 
    chat.quiz = quiz;


    PS: правда это не совсем очередь, но ваш global_quizzes в некоторой степени ее имитирует.
    Ответ написан
    2 комментария
  • Как сделать постоянное соединение grpc nodejs?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Комментировать
  • Можно ли сделать переменные, определяемые в методе .exec, глобальными?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Для начала разбор Вашего варианта:
    var all_mail;
    mailModel.find().exec((err, docs) =>{
         // данный код не будет выполнен сразу, он будет выполнен только через какоето время.
         // дело в том, что пока бд сделает выборку и отдаст результат 
         // может пройти определенное время. Чтобы избежать простоев, 
         // в данном случае метод exec выполняется асинхронно
         // то есть тело данной функции будет вызвано не ранее чем от БД будут получены данные
         // а js тем временем продолжит выполнение кода дальше
         all_mail = docs;
    });
    
    // и придет сюда. но так как docs от БД еще не получен, all_mail все еще равен undefined.
    console.log(all_mail);  // Ошибка


    Теперь посмотрим как же нам добиться своевременной обработки результата:
    // добро пожаловать в асинхронность
    var all_mail;
    
    mailModel.find().exec((err, docs) =>{
         // в all_mail засовываем промис(обещание) того, что в скором времени будет результат
         all_mail  = new Promise((resolve, reject)=>{
               resolve(docs);
         });
    
    });
    
    all_mail.then((data)=>{
         // когда же результат будет получен, обрабатываем его
         console.log(data);  // все ок)
    });
    Ответ написан
    7 комментариев
  • Как запустить бинарный поток с клиента на сервер?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Можно, через websocket. Есть даже готовый npm пакет для этих целей websocket-stream

    Use HTML5 websockets using the Node Streams API.

    Usage
    This module works in Node or in Browsers that support WebSockets. You can use browserify to package this module for browser use.


    Или вам нужен чистый http?
    Ответ написан
    4 комментария
  • Как запустить приложение на разных субдоменах?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Думаю самым простым и правильным решением будет разруливать субдомены и соответственно висящие на них приложения через nginx.

    Вы сможете запускать свои приложения как на одном хосте и даже в одном докер контейнере (на разных портах) так и на разных хостах и перенаправлять входящие по 80 порту запросы на ваши приложения по признаку субдомена. Так же вы сможете получив один сертификат выписанный для основного домена и субдоменов и подключив его через nginx, вы получите https не заморачиваясь настройкой и подключением сертификатов непосредственно в коде ваших приложений. Так же вы получите удобный инструмент балансировки нагрузки между вашими субдоменами и много других плюшек.
    Ответ написан
    Комментировать
  • Как сделать свою обёртку fs?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    const fs = require('fs');
    
    ...
    
    exports.readdir = fs.readdir;
    Ответ написан
    Комментировать
  • Как запустить bat файл от имени админа или exec на node.js в windows?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Запустите ваш index.js под админом
    runas /user:username "node index.js"

    Где username имя пользователя-администратора
    Ответ написан
    3 комментария
  • Как понять сколько тредов способна выдержать node.js?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Очень часто под трэдами имеют ввиду как потоки так и параллельные процессы.

    Если под трэдами вы подразумеваете процессы, то в nodejs они реализуются с помощью worker-ов. других реализаций насколько я знаю в ноде нет. Про них немного написано тут и тут (в комментариях намекают на тесты производительности и прочего, возможно даже кто то проводил оные)
    Если же вы интересуетесь потоками, то о с ними можно немного ознакомится тут

    Для более развернутого ответа хотелось бы более развернутый вопрос.
    Ответ написан
    9 комментариев
  • Express js что не так с роутингом?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    сделайте роутер auth так:

    const express = require('express');
    const router = express.Router();
    
    router.get('/', (req, res) => res.render('/auth'));
    router.post('/', (res, req) => {
      console.log(req.body);
      res.json({
        ok: true
      });
    });
    
    module.exports = router;
    Ответ написан
    4 комментария
  • Как отловить в коде что IP заблокирован?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Таймаут реквесту поставить. Если ответ не пришел до истечения таймаута, то "не ок"
    Не знаю возможности модуля request и посмотреть нормально не могу, с телефона не удобно, поэтому могу предложить только универсальное, но не очень верное идеологически решение:

    var options = {
      url: url,
      encoding: null,
      timeout: 60*1000
    };
    
    function req(opts, cb){
      var isTimeout = false;
      setTimeout( ()=>{
         if( isTimeout) return;
         isTimeout = true;
         cb("time is out", {});
      }, opts.timeout);
      request.get(opts, function (err, res) {
      // сюда не попадает уже.. ;) виснет на запросе.
        if( isTimeout ) return;
        isTimeout = true;
        cb(err, res);
      });
    )
    
    // выполняем запрос с таймаутом в 60 сек.
    req(options, function(err, res){
        if (err) {
            console.log('не ok');
        } else {
            console.log('ok');
        }
    });


    PS: правильным решением будет делать так как это сделано в Вашем примере, но добавив в options значение таймаута. Поищите в офдоке модуля request как это делать.
    Ответ написан
    Комментировать
  • Какую БД выбрать для Electron-приложения?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    для реляционной БД - SQLite
    для NOSQL БД - nedb (хабр. nedb полностью встраиваемая в приложение, почти в полном объеме реализует систему запросов как в mongodb)
    Ответ написан
    Комментировать