Развертывание приложения для живого чата по проблемам Heroku (Node.js)

В настоящее время я пытаюсь внедрить функцию живого чата на своем веб-сайте с помощью Node.js и Heroku. Я сделал все возможное, чтобы выполнить следующие шаги для развертывания безрезультатно: http://tutorialzine.com/2014/03/nodejs-private-webchat/

Я создал исходный чат-сервер, просмотрев следующие обучающие видео: https://www.youtube.com/playlist?list=PLfdtiltiRHWHZh8C2G0xNRbcf0uyYzzK_

Одна вещь, которая меня озадачивает, это то, что у меня нет файла app.js, который описан в пошаговом руководстве по первой ссылке, которую я разместил. Это просто похоже на мой server.js?

Вот мой код:

HTML (ОБНОВЛЕНО): (у меня есть скрипт на пару строк ниже кода src="http://127.0.0.1:8080/socket.io/socket.io.js" мне нужно удалить/отредактировать это? Я' мы уже удалили локальный хост из var socket = io.connect();)

<!DOCTYPE html>
            <html>
              <head>
                <title>Chat</title>
                <link rel="stylesheet" href="main.css">
              </head>



              <body>
                <div class="all-content">
                <div class="header-bar">
                  <div class="bar">
                      <img src="C:\Users\jlewa\Desktop\assets\affinity_fm_only_letters.png" class="top-logo" style="float: left;">
                      <ul class="standard-nav" style="float: left;">
                        <li>Home</li>
                        <li>Lyrics Hub</li>
                        <li>Affinity LIVE</li>
                        <li>Merchandise</li>
                      </ul>
                  </div>
                  <div class="dropshadow"></div>
                </div>

                <div class="container-middle-third">
                  <div class="youtube-video" style="float: left;">
                    <div class="DJ-text">Affinity FM DJ Room</div>
                    <div class="DJ-underline"></div>
                    <div id="player" style="width: 1280px; height: 720px;"></div>
                  </div>
                  </div>

                  <div class="chat" style="float: left;">
                    <div class="Chat-text">Chat</div>
                    <div class="Chat-underline"></div>
                    <input type="text" class="chat-name" placeholder="Chat">
                        <div class="right-tab">
                            <div class="info-rect">INFO</div>
                        </div>
                    <div class="chat-messages"></div>
                    <textarea placeholder="Join the conversation..."></textarea>
                    <div class="chat-status">Status: <span>Idle</span></div>
                  </div>

                <div class="bottom-bar">

                  <img src="C:\Users\jlewa\Desktop\assets\affinitylogo.png" class="thumbnail" id="thumbnail" style="float: left">

                  <div class="title-bar" style="float: left;">

                    <div class="title" id="title"></div>
                    <div class="dj-playing">Affinity FM is playing</div>

                    <div class="progress-background">
                      <div id="progress-bar" class="progress-bar"></div>
                    </div>

                  </div>
                  <div class="subscribe" style="float: left;">



                    <div class="sub-container">

                        <div class="g-ytsubscribe" data-channel="SAMusicPlaylist" data-layout="full" data-theme="dark" data-count="default"></div> 



                    </div>


                  </div>

                </div>

     <!--do i need to get rid of this script? --> <script src="/socket.io/socket.io.js"></script>

                <script src="https://apis.google.com/js/platform.js"></script>

                <script>
                  (function() {
                    var getNode = function(s) {
                      return document.querySelector(s);
                    },

                        // Get required nodes
                        status = getNode('.chat-status span'),
                        messages = getNode('.chat-messages'), 
                        textarea = getNode('.chat textarea'),
                        chatName = getNode('.chat-name'),

                        statusDefault = status.textContent,    

                        setStatus = function(s){
                          status.textContent = s;

                          if(s !== statusDefault){
                            var delay = setTimeout(function(){
                              setStatus(statusDefault);
                              clearInterval(delay);
                            }, 3000);
                          }
                        };

                    //try connection
                    try{
                      var socket = io.connect(); <!--removed localhost -->
                    } catch(e){
                      //Set status to warn user
                    }

                    if(socket !== undefined){

                      //Listen for output
                      socket.on('output', function(data){
                        if(data.length){
                          //Loop through results
                          for(var x = 0; x < data.length; x = x + 1){
                            var message = document.createElement('div');
                            message.setAttribute('class', 'chat-message');
                            message.textContent = ': ' + data[x].message;
                            var name=document.createElement('span');
                            name.setAttribute('class', 'userName');
                            name.textContent = data[x].name;

                            message.insertBefore(name, message.firstChild);

                            //Append
                            messages.appendChild(message);
                            messages.insertBefore(message, messages.firstChild);
                          }
                        }
                      });

                      //Listen for a status
                      socket.on('status', function(data){
                        setStatus((typeof data === 'object') ? data.message : data);

                        if(data.clear === true){
                          textarea.value = '';
                        }
                      });

                      //Listen for keydown
                      textarea.addEventListener('keydown', function(event){
                        var self = this,
                            name = chatName.value;

                        if(event.which === 13 && event.shiftKey === false){
                          socket.emit('input', {
                            name: name,
                            message: self.value
                          });
                        }
                      });
                    }

                  })();
                </script>
                <script>
                  var time_total;
                  var timeout_setter;
                  var player;
                  var tag = document.createElement("script");//This code loads the IFrame Player API code asynchronously

                  tag.src = "https://www.youtube.com/iframe_api";
                  var firstScriptTag = document.getElementsByTagName("script")[0];
                  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

                  //This function creates an <iframe> (and YouTube player) OR uses the iframe if it exists at the "player" element after the API code downloads
                  function onYouTubeIframeAPIReady()
                  {
                    player = new YT.Player("player",
                                           {
                      height: "853",
                      width: "480",
                      /* videoId: "GGmxVDXM5X2UxaP9PvWQ4Z171DXyGcq", */
                      playerVars: {
                        listType:'playlist',
                        list: 'PL_GGmxVDXM5X2UxaP9PvWQ4Z171DXyGcq',
                        controls: '0',
                        html5: '1',
                        cc_load_policy: '0',
                        disablekb: '1',
                        iv_load_policy: '3',
                        modestbranding: '1',
                        showinfo: '0',
                        rel: '0',


                      },
                      events:
                      {
                        "onReady": onPlayerReady,
                        "onStateChange": onPlayerStateChange
                      }

                    });
                  }


                var num = (1 + Math.floor(Math.random() * 10));


                  //The API will call this function when the video player is ready
                  function onPlayerReady(event)
                  {
                    event.target.playVideo();
                    time_total  = convert_to_mins_and_secs(player.getDuration(), 1);
                    loopy();


                    player.addEventListener('onStateChange', 'onPlayerStateChange');


                    player.setShuffle( {
                    'shufflePlaylist': 1
                    } );    
                  }

                  function loopy()
                  {
                    var current_time = convert_to_mins_and_secs(player.getCurrentTime(), 0);
                    document.getElementById("progress-bar").style.width = (player.getCurrentTime()/player.getDuration())*100+"%";
                    console.log( current_time + " / " + time_total);
                    timeout_setter = setTimeout(loopy, 300);
                  }

                  function convert_to_mins_and_secs(seconds, minus1)
                  {
                    var mins    = (seconds>=60) ?Math.round(seconds/60):0;
                    var secs    = (seconds%60!=0) ?Math.round(seconds%60):0;
                    var secs    = (minus1==true) ?(secs-1):secs; //Youtube always displays 1 sec less than its duration time!!! Then we have to set minus1 flag to true for converting player.getDuration()
                    var time    = mins + ":" + ((secs<10)?"0"+secs:secs);
                    return time;
                  }

                  // 5. The API calls this function when the player's state changes
                  function onPlayerStateChange(event)
                  {
                    if (event.data == YT.PlayerState.ENDED)
                    {
                      console.log("END!");
                      clearTimeout(timeout_setter);
                      document.getElementById("progress-bar").style.cssText = "transition: none;";


                    }
                    else if (event.data == YT.PlayerState.PLAYING)
                    {
                      console.log("PLAYING");
                      loopy();
                      document.getElementById("progress-bar").style.cssText = "transition: all 300ms linear 0s;";
                      console.log(player.getPlayerState());
                      if (player.getPlayerState() == 1) {
                      document.getElementById( "title" ).innerText = player.getVideoData().title;
                        }
                    }
                    else if (event.data == YT.PlayerState.PAUSED)
                    {
                        event.target.playVideo();
                        console.log("PLAUSED");
                    }
                    else
                    {
                      console.log(event.data);
                    }
                  }
                </script>

                <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
               <!-- <script>
                    function make_request()
                    {
                        var response        = "";
                        var response1       = "thumbnail";
                        var api_key         = "AIzaSyApWxw8xp1qw09ByArSLD0XABQrE40cKEw";
                        var play_list_id    = "PL_GGmxVDXM5X2UxaP9PvWQ4Z171DXyGcq";
                        var url             = "https://www.googleapis.com/youtube/v3/playlists?part=snippet&id=" + play_list_id + "&key=" + api_key;

                        $.ajax
                        ({
                            url: url,
                            dataType: "json",
                            type: "get",
                            async: false,
                            success: function(data)
                            {
                                response = JSON.stringify(data);
                                response1 = data;
                            }
                        });
                        alert(response1.items[0].snippet.thumbnails.default.url);
                        console.log(response1.items[0].snippet.thumbnails.medium.url);
                        console.log(response);
                    }

                    function init()
                    {
                        gapi.client.setApiKey("AIzaSyApWxw8xp1qw09ByArSLD0XABQrE40cKEw");
                        gapi.client.load('youtube', 'v3').then(make_request);
                    }
                  </script>
                  <script src="https://apis.google.com/js/client.js?onload=init"></script> -->
                    </div>
              </body>

           </html>

Server.js: (Я использовал Mongo для локального хостинга, нужно ли мне удалять некоторые вещи с локального хоста?)

var mongo = require('mongoDB').MongoClient,
    client = require('socket.io').listen(8080).sockets;

mongo.connect('mongodb://127.0.0.1/chat', function(err, db) {
    if(err) throw err;

    client.on('connection', function(socket){

        var col = db.collection('messages'),
            sendStatus = function(s){
                socket.emit('status', s);   
            };

        //Emit all messages
        col.find().limit(100).sort({_id: 1}).toArray(function(err, res) {
            if(err) throw err;
            socket.emit('output', res);
        });

        //wait for input
        socket.on('input', function(data){
            var name = data.name,
                message = data.message,
                whitespacePattern = /^\s*$/;

            if(whitespacePattern.test(name) || whitespacePattern.test(message)){
                sendStatus('Name and Message is required.');
            } else {
                col.insert({name: name, message: message}, function(){

                    //Emit latest message to ALL clients
                    client.emit('output', [data]);

                  sendStatus({
                      message: "Message sent",
                      clear: true
                  });

                });   
            }

        });

    });

});

package.json (ОБНОВЛЕНО):

  {
  "name": "live-chat",
  "version": "1.0.0",
  "engines":{
    "node": "4.4.5"
},
  "description": "a live chat for Affinity LIVE",
  "main": "server.js",
  "dependencies": {
    "mongodb": "^2.1.18",
    "socket.io": "^1.4.6"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "keywords": [
    "live",
    "chat"
  ],
  "author": "Jordan Lewallen",
  "license": "ISC"
}

Журнал Heroku (ОБНОВЛЕНО):

2016-06-22T05:42:21.990238+00:00 app[web.1]: npm ERR!     npm owner ls live-chat
2016-06-22T05:42:21.998667+00:00 app[web.1]: npm ERR!     /app/npm-debug.log
2016-06-22T05:42:23.128513+00:00 heroku[web.1]: Process exited with status 1
2016-06-22T05:42:23.147472+00:00 heroku[web.1]: State changed from starting to crashed
2016-06-22T05:42:24.269961+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=young-wave-94499.herokuapp.com request_id=0a4b2290-a946-49a5-9f67-e216aa71e33e fwd="23.92.9.183" dyno= connect= service= status=503 bytes=

Это ошибка, которую я получаю, когда набираю «heroku open» в командной строке cmd:

введите здесь описание изображения


person Jordan Lewallen    schedule 22.06.2016    source источник
comment
можешь показать мне логи хероку? и, пожалуйста, добавьте ключ запуска в файл package.json   -  person uzaif    schedule 22.06.2016
comment
и вы забыли определить свою зависимость в package.json   -  person uzaif    schedule 22.06.2016
comment
Привет @uzaif Я обновил свой пост в журнале и, кажется, добавил ключ запуска в файл package.json. Не могли бы вы объяснить, что мне нужно сделать для зависимости? Спасибо за помощь!   -  person Jordan Lewallen    schedule 22.06.2016
comment
какие модули вы установили в этом приложении npm install   -  person uzaif    schedule 22.06.2016
comment
@uzaif о, попался, потратил некоторое время на это, и я думаю, что package.json работает правильно (хотя все еще ошибки). Я обновил этот текст и НОВЫЙ журнал ошибок приложения в своем исходном сообщении.   -  person Jordan Lewallen    schedule 22.06.2016
comment
на каком порту работает ваш сервер?   -  person uzaif    schedule 22.06.2016


Ответы (2)


В файле package.json вам необходимо включить:

  1. любые зависимости, которые у вас есть

  2. раздел под названием «двигатели», где вы указываете версию используемого вами узла.

Обязательно ознакомьтесь с этой ссылкой на героку: https://devcenter.heroku.com/articles/deploying-nodejs

person Clay James    schedule 22.06.2016
comment
спасибо за информацию, просмотрел и обновил зависимости и движки в package.json. Я обновил код для этого и НОВЫЙ журнал ошибок в своем исходном сообщении. - person Jordan Lewallen; 22.06.2016
comment
@Jordan-Lewallen heroku устанавливает свой собственный порт. попробуйте заставить socket.io слушать: (process.env.PORT || 8080) - person Clay James; 22.06.2016
comment
Я изменил строку index.html на var socket = io.connect('process.env.PORT || 8080'); с ошибкой приложения. Что я могу отправить, что облегчит вам отладку? - person Jordan Lewallen; 22.06.2016
comment
Я думаю, что html файл был хорош, как это было (вы не должны указывать порт там). Я имел в виду изменить порт в server.js в строке 2. Что касается отправки чего-либо еще, я думаю, что журналы heroku в порядке. - person Clay James; 22.06.2016
comment
О, я вижу, моя вина. Изменена строка 2 server.js на client = require('socket.io').listen(process.env.PORT || 8080).sockets; также в другом ответе было запрошено, чтобы моя строка mongo.connect была изменена на что-то, что может достичь героку. Итак, я настроил mLab и поместил это в строку 4 server.js: ) выбросить ошибку; кстати, все еще получаю ошибку приложения - person Jordan Lewallen; 22.06.2016
comment
отредактировал комментарий, вероятно, после того, как вы открыли ответ о том, что он все еще не работает @Clay James - person Jordan Lewallen; 22.06.2016
comment
Ах да, я вижу это сейчас. Ну, если это не исправило, я не уверен, что еще делать. Я предполагаю, что это проблема MongoDb, но я никогда не работал с этим раньше, поэтому я не уверен, как это исправить. Я нашел одну подходящую ссылку, чтобы указать вам на нее: stackoverflow.com/questions/18076335/ удачи вам. - person Clay James; 22.06.2016
comment
спасибо, что прислали ссылку, я думаю, что это тоже монго... Я не смог заставить ее работать. Вернемся к поиску. Спасибо за ваше время - person Jordan Lewallen; 23.06.2016

Вам нужно будет настроить URL-адрес вашей mongoDB так, чтобы он мог достичь героку. Вы можете настроить это с помощью такой службы, как mLab.

mongo.connect('mongodb://mongodb.example.com/database', function(err, db) { ... });

Прямо сейчас он просто указывает на локальную машину.

Для вашего html вам также нужно будет изменить URL-адреса. Что-то вроде этого, вероятно, сработает:

<script src="/socket.io/socket.io.js"></script>

Я видел еще пару вещей, указывающих на вашу локальную машину.

person Sebastian    schedule 22.06.2016
comment
Привет @Sebastian, я пытаюсь настроить базу данных mLab. Один из первых шагов гласит, что мне нужно подключиться с помощью оболочки mongo: mongo ds021434.mlab.com:21434/heroku_ccsbtmfd -u ‹dbuser› -p ‹dbpassword›, когда я ввожу имя пользователя и передаю пароль, я получаю аутентификацию не удалось. Я также использовал свое имя пользователя и пароль для базы данных (они сказали, что это распространенная проблема) - person Jordan Lewallen; 22.06.2016