-
[진행중] promise 이해하기discord-bot.project.log 2022. 2. 28. 02:25
질문 내용
하고 싶은 것 fetch로 채널 값을 얻어오고, cache로 저장하고 싶었다.지난 이야기 지난 번에 client.channels.cache.get()으로 채널정보를 가져오지 못한 이유는 fetch를 하지 않고 cache를 하려고 했기 때문이었다. 그래서 fetch 메서드를 discord.js문서에서 찾아보고
먼저 fetch로 날리고 캐시해보려고 했는데 TypeError: Cannot read properties of undefined (reading 'then')이라는 에러가 떴다.const channel = client.channels.fetch('내채널의 snowflake값') const cachedChannel = client.channels.cache.get(channel) .then(console.log(cachedChannel)) .catch(console.error);
생각해본 것에러메세지가 이해가 안가는 점은 먼저 fetch를 날리고 그 값이 오면 then이 실행되는 거는 거라고 생각하니 undefined되었다는 게 이해가 되지 않았다.시도해본 것그래서 무작정 fetch를 날리고 console.log(channel)을 했을 때는 null값이 떴다. 제가 말한 "값이 도착하면 then이 실행되는 것"이라는 추측이 틀린건가 생각했다.관련문서Discord.js
Discord.js is a powerful node.js module that allows you to interact with the Discord API very easily. It takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code significantly tidier and easier to comprehend.
discord.js.org
Discord.js
Discord.js is a powerful node.js module that allows you to interact with the Discord API very easily. It takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code significantly tidier and easier to comprehend.
discord.js.org
답변
이건...비동기에요 fetch 도 비동기니까 디코 서버에 요청을 보낸 뒤에 비동기면 다음 문장으로 바로 진행하니까const channel <- 이 친구에는 promise가 들어있을 거고 그 값이 들어있지 않았는데 바로 cache에서 값을 꺼내려 하면 없는 거죠나의 생각
promise가 fulfilled되고 난 이후에 cache로 값을 꺼내면 되겠다는 생각을 했다.
MDN의 프로미스 설명
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
Promise - JavaScript | MDN
Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.
developer.mozilla.org
프로미스는 3가지 상태를 가진다.
- 대기(pending): 이행하지도, 거부하지도 않은 초기 상태.
- 이행(fulfilled): 연산이 성공적으로 완료됨.
- 거부(rejected): 연산이 실패함.
대기 중인 프로미스는 값과 함께 이행할 수도, 어떤 이유(오류)로 인해 거부될 수도 있습니다. 이행이나 거부될 때, 프로미스의 then 메서드에 의해 대기열(큐)에 추가된 처리기들이 호출됩니다. 이미 이행했거나 거부된 프로미스에 처리기를 연결해도 호출되므로, 비동기 연산과 처리기 연결 사이에 경합 조건은 없습니다. 이거 뭔소리지?
Promise.prototype.then() 및 Promise.prototype.catch() (en-US) 메서드의 반환 값은 새로운 프로미스이므로 서로 연결할 수 있습니다.
= then()과 catch()의 반환값은 새로운 Promise다.
프로미스가 pending 상태 이후에,
값이 fulfill(Promise.resolve를 실행시킨 경우) 되거나 reject 될 수 있다. (경우의 수가 2가지)
값이 반환 되고 나면(fulfill) then()은 Promise을 반환한다.
값이 반환되지 않으면(reject) then이 있으면 then을 실행하고 Promise를 반환하고, 그 이후 catch를 실행하고 Promise를 반환한다.
then은 일종의 계획이다 async도 일종의 계획이다(그냥 두 가지 방법이 있을 뿐이다.)
그런데 await는 값이 반환될 때 까지 기다리겠다는 일종의 계획이다. (실행시키는 건 아님)
그래서 값이 fulfilled 되고 난 후에 그 값을 이용해 무언가를 하겠다라는 함수를 작성한다면 await (값이 fulfilled될때까지 기다릴 거야! 라고 계획을 세울 수 있는 것이다.)
Promise.prototype.then() - JavaScript | MDN
then() 메서드는 Promise (en-US)를 리턴하고 두 개의 콜백 함수를 인수로 받습니다. 하나는 Promise가 이행했을 때, 다른 하나는 거부했을 때를 위한 콜백 함수입니다.
developer.mozilla.org
Promise의 순서 연습
import "./styles.css"; const cache = []; async function getChannel() { console.log("프로미스 생성!"); return new Promise((resolve) => setTimeout(() => { resolve("나는 채널!"); }, 100) ); } async function getCache() { return cache[0]; } async function go() { const channelPromise = getChannel(); const channel = await channelPromise; cache[0] = channel; console.log("채널을 캐시에 저장했습니다", channel); const cachedChannel = await getCache(); console.log("캐시에서 채널을 꺼냈습니다", cachedChannel); return "끝났습니다" } console.log("first"); go().then(console.log); console.log("second");
'discord-bot.project.log' 카테고리의 다른 글
discord.js 특정채널에서만 interaction하게 만들기 (0) 2022.03.08 node index.js 입력하기 귀찮아서 찾아본 nodemon (0) 2022.03.04 함수 리팩토링 (0) 2022.02.24 [Discord.js] interaction 탐구하기 (0) 2022.02.23 node-fetch 관련해서 공부한 링크.archive (0) 2022.02.21