2016-12-08 1 views
2

내 문제는 아래 보이는 것처럼 코드가 순서대로 실행되지 않는 것입니다.이 코드는 순서대로 실행되지 않는 것 같습니다.

이 코드는 내가 만들고있는 제 discord.js bot 용입니다.



    var Discord = require("discord.js"); 
    var bot = new Discord.Client(); 
    var yt = require("C:/Users/username/Documents/Coding/Discord/youtubetest.js"); 
    var youtubetest = new yt(); 
    var fs = require('fs'); 
    var youtubedl = require('youtube-dl'); 
    var prefix = "!"; 
    var vidid; 
    var commands = { 
     play: { 
     name: "!play ", 
     fnc: "Gets a Youtube video matching given tags.", 
     process: function(msg, query) { 
     youtubetest.respond(query, msg); 
     var vidid = youtubetest.vidid; 
     console.log(typeof(vidid) + " + " + vidid); 
     console.log("3"); 
     } 
    } 
    }; 

    bot.on('ready',() => { 
     console.log('I am ready!'); 
    }); 

    bot.on("message", msg => { 
     if(!msg.content.startsWith(prefix) || msg.author.bot || (msg.author.id === bot.user.id)) return; 

     var cmdraw = msg.content.split(" ")[0].substring(1).toLowerCase(); 
     var query = msg.content.split("!")[1]; 
     var cmd = commands[cmdraw]; 
     if (cmd) { 
     var res = cmd.process(msg, query, bot); 
     if (res) { 
      msg.channel.sendMessage(res); 
     } 
     } else { 
     let msgs = []; 
     msgs.push(msg.content + " is not a valid command."); 
     msgs.push(" "); 
     msgs.push("Available commands:"); 
     msgs.push(" "); 
     msg.channel.sendMessage(msgs); 
     msg.channel.sendMessage(commands.help.process(msg)); 
     } 
    }); 

    bot.on('error', e => { console.error(e); }); 
    bot.login("mytoken"); 

youtubetest.js 파일 : 코드에서 볼 수 있듯이



    var youtube_node = require('youtube-node'); 
    var ConfigFile = require("C:/Users/username/Documents/Coding/Discord/json_config.json"); 
    var mybot = require("C:/Users/username/Documents/Coding/Discord/mybot.js"); 

    function myyt() { 
     this.youtube = new youtube_node(); 
     this.youtube.setKey(ConfigFile.youtube_api_key); 
     this.vidid = ""; 
    } 

    myyt.prototype.respond = function(query, msg) { 
     this.youtube.search(query, 1, function(error, result) { 
     if (error) { 
      msg.channel.sendMessage("There was an error finding requested video."); 
     } else { 
      vidid = 'http://www.youtube.com/watch?v=' + result.items[0].id.videoId; 
      myyt.vidid = vidid; 
      console.log("1"); 
     } 
     }); 
     console.log("2"); 
    }; 

    module.exports = myyt; 

, 내가 봇 처리 할 수있는 명령에 대한 객체를 가지고 있고, 내가 실행하는 기능을 갖는 것을 명령 메시지를받을 때. 코드 전체에서 3 개의 console.log를 1, 2 및 3과 함께 배치하여 코드의 일부가 실행될 것으로 예상되는 순서를 보여줍니다. 코드가 실행되고 쿼리가 발견되면 출력은 다음과 같습니다.

이렇게하면 코드가 잘못된 순서로 실행되고 있음을 알 수 있습니다.

모든 도움은 매우 매우 감사합니다 :)

* 업데이트! 왜 그것이 작동하지 않는지 이해해 주셔서 대단히 감사합니다. 내가 주 파일에서 vidid = youtubetest.respond(query, msg)에있는 해결책을 찾았는데, 함수가 완료 될 때까지 변수가 할당되지 않으므로 변수없이 내 코드의 나머지 부분으로 넘어갑니다. 단순히 변수 정의되지 않은 경우 경우 확인하고이 정의 될 때까지 기다리는 if 문을 넣어 해결하려면. *

+0

비동기 코드를 작성하고 있습니다. console.log 2는 비동기 함수 밖에 있습니다. 네가 무슨 일이 일어날 지 모르겠다. – Erik

+0

미안하지만, 나는 그런 종류의 일을 많이하지 않았고, 나는 10 대이고 여전히 자바 스크립트를 배우고 있습니다. 비동기를 정확히 의미하는 것은 무엇이며, 어떤 부분이 있고 그렇지 않은지? –

+0

'this.youtube.search'는 아마도 비동기 함수입니다. 즉, 함수의 * 콜백 * 외부에있는 다른 코드가 계속 실행되는 동안 백그라운드에서 무언가를 수행한다는 의미입니다. 그래서 당신의'function (error, result) {...}'는 검색 연산이 완료된 후에 * 만 실행하는 콜백입니다. 따라서'console.log (2)'는 당연히 콜백 전에 호출된다. – Fissio

답변

2

는 물건을 많이는 자바 스크립트, 비동기에 따라서 콜백 핸들러를 실행합니다. 비동기로 실행되는 이유는 나머지 코드가 원격 호출에 의해 "차단"되는 것을 피하기 위해서입니다. 콜백 지옥에서 끝내지 않기 위해서, 우리 대부분은 자바 개발자들은 점점 더 Promises으로 이동하고 있습니다. 그래서 코드는 더 같이 수 :

myyt.prototype.respond = function(query, msg) { 
     return new Promise(function(resolve, reject) { 
      this.youtube.search(query, 1, function(error, result) { 
       if (error) { 
        reject("There was an error finding requested video."); // passed down to the ".catch" statement below 

       } else { 
        vidid = 'http://www.youtube.com/watch?v=' + result.items[0].id.videoId; 
        myyt.vidid = vidid; 
        console.log("1"); 
        resolve(2); // Resolve marks the promises as successfully completed, and passes along to the ".then" method 
       } 
      }); 
     }).then(function(two) { 
      // video is now the same as myyt.vidid as above. 
      console.log(two); 
     }).catch(function(err) { 
      // err contains the error object from above 
      msg.channel.sendMessage(err); 
     }) 
    }; 

이 자연스럽게이 프로세스를 사용하여 어떤 변화를 필요로하지만 자신의 프로토 타입을 만드는 것은 .. 이상한 것 같다 것입니다.

이 약속은 생생를 반환, 그래서 당신은 다음 vidid = youtubetest.response(query, msg);을 설정할 것, 그 함수가 호출 될 때마다, 당신이 할 :

vidid.then(function(id) { 
// id is now the vidid. 
}); 

자바 스크립트가 설계 상 비동기 실행하고, 그 리드의 주위에 당신의 방법을 해킹 시도 당신은 어두운 곳으로 빨리갑니다. 내가 말할 수있는 한 nodeJS도 타겟팅하고 있습니다. 즉, 동기식으로 뭔가를 실행하면 모든 사용자가 동기화 호출이 끝나기를 기다려야하므로 다른 사용자의 성능을 중지하게됩니다.

일부 제안 읽기 :

I 좋겠 또한 코드를 단축하고 생활이 hellofalot 쉽게로, ES6 구문을 찾는 것이 좋습니다 (기본 약속은 NodeJS 4 이상에서 지원되는 ES6에서만 도입되었습니다)

+0

고마워요, 제 질문에 대해 설명하는 데 도움이됩니다.하지만 질문이 잘못되었다는 것을 알았지 만 여전히 큰 도움이됩니다. 고마워요! :) –

0

을 자바 스크립트에서, 당신은 다른 함수에 전달되는 콜백 함수가 비동기 적으로 호출되는 것을 기억하시기 바랍니다. 나는. 콜백 함수에 대한 호출이 "순서대로"발생하지 않을 수 있습니다. 이 경우 "순서대로"는 소스 파일에 나타나는 순서를 의미합니다.

콜백 함수는 단순히 특정 이벤트라고

:

  • 처리 할 데이터가 YouTube 검색 결과 준비가되었을 때, '예를 들어, 귀하의 경우 오류
  • ready '이벤트가 수신되었거나'message '가 수신되었습니다.
  • 처럼 이전에 언급
+0

아, 그렇긴하지만 어떻게 youtube 검색의 결과와 함께 mybot.js에 변수'vidid'를 다시 가져올 수 있습니까? 아마도 질문에 더 잘 지정해야합니다. –

+0

그 때 또 다른 질문입니다. :-) 당신의 play 함수에서, vidid 변수의 시작 부분에서 'var'을 제거하면 vidid 변수를 무시할 수 있습니다. – teroi

+0

그런 다음 코드의 다른 위치에서 vidid! ==가 정의되지 않았는지 확인하고 사용하십시오. – teroi

관련 문제