약속을 포착하여 자리 표시자 데이터 제공
15246 단어 slackbotspromisesjavascript
이것은 "Hack Day"프로젝트였기 때문에 초기 구현은 그 이름에 걸맞게 매우 해키했습니다. 투표는 서버에 저장되지 않았습니다. 사용자는 원하는 만큼 투표할 수 있습니다. POST
/handle-vote
요청(지속성 계층으로서의 Slack 😂)과 함께 제공된 문자열을 수정하여 투표를 처리했습니다.// text => 'Yes: 0 No: 0'
// value => 'yes' || 'no
function updateAttachmentText(text, value) {
votes = text.split(' ')
if (value === 'no') {
votes[3] = parseInt(votes[3]) + 1
} else if (value === 'yes') {
votes[1] = parseInt(votes[1]) + 1
}
return votes.join(' ')
}
const updated = updateAttachmentText('Yes: 0 No: 0', 'yes')
// => 'Yes: 1 No: 0'
이 해킹된 작은 봇은 우리 제품 팀에 매우 유용한 것으로 밝혀졌습니다. 그러나 저는 그 어둡고 끔찍한 비밀을 알고 투표 데이터 저장을 위해 Redis를 사용하는 보다 강력한 버전을 작성하기로 결정했습니다. 한 사용자가 여러 번 투표합니다.
봇 자체는 크론 작업을 사용하여 채널에 새로운 피드백을 게시합니다. 업그레이드하는 동안 해당 피드백의 ID로 새 "빈"레코드를 생성하는 단계를 해당 스크립트에 추가했습니다.
const initialVotes = { votes: { yes: [], no: [] } }
redisClient.store(id, JSON.stringify(initialVotes))
사용자가 버튼을 누르면 서버는 요청을 받고 ID로 피드백을 찾고 사용자 ID를 올바른 목록('예' 또는 '아니요')에 추가한 다음 Redis 스토어에 다시 저장합니다. 사용자가 단 한 번만 투표할 수 있도록 몇 가지 논리를 수행합니다.
여기서 문제는 원래 봇의 메시지와 관련된 것입니다. 이러한 피드백 비트에는 애플리케이션의 ID와 연결된 레코드가 없습니다. 따라서 사용자가 투표 버튼을 클릭하면 다음 코드는 실패합니다.
// Imagine our Redis client setup...
class Redis {
// setup, etc
fetch(key) {
return new Promise((resolve, reject) => {
this.client.get(key, (err, response) => {
if (err || !response) {
return reject('Unable to find result for', key, err)
}
return resolve(response)
})
})
}
}
// ... and a Vote loading class...
class Vote {
constructor(id, redisClient) {
this.id = id
this.redisClient = redisClient
}
loadVote() {
return this.redisClient.fetch(this.id)
.then(voteData => JSON.parse(voteData))
}
}
const vote = new Vote(someId, someRedisClient)
vote.loadVote().then((vote) => incrementCounterAndSave(vote))
// Uncaught rejection :(
처음에는 이것이 내 서버 코드 어딘가에 존재하지 않는 레코드를 처리하기 위해 조건부 논리가 필요한 성가신 문제라고 생각했습니다. 하지만
Vote
클래스의 코드 자체를 보면 더 깔끔한 옵션이 나타납니다.class Vote {
// ...
loadVote() {
return this.redisClient.fetch(this.id)
.then(voteData => JSON.parse(voteData))
.catch((err) => {
console.log('Encountered an error, returning placeholder data:', err)
return { votes: { yes: [], no: [] } }
})
}
}
const vote = new Vote(someId, someRedisClient)
vote.loadVote()
.then((vote) => {
console.log(vote)
incrementCounterAndSave(vote)
})
// Encountered an error, returning placeholder data:
// 'Unable to find result for someId (error here)
// { votes: { yes: [], no: [] } }
한동안 Promise와 함께 일하면서 이 개념이 내 첫 번째 직감이 아니었기 때문에 이 글을 써야겠다고 생각했습니다.
catch
를 체인의 맨 끝에서 사용할 생각은 없었습니다. then
통화 중.다음은 이것을 매우 간단하게 보여주는 콘솔에서 놀 수 있는 몇 가지 코드입니다!
class DataFetcher {
constructor() {
this.count = 0
}
fetch() {
this.count += 1
return new Promise((resolve, reject) => {
// Cause this Promise to be rejected/fail every other time the fetch function is called.
this.count % 2 === 0 ? resolve('data from DB!') : reject('data not found')
})
}
}
const client = new DataFetcher()
const getData = () => {
return client.fetch()
.then((res) => {
return res
})
.catch(err => {
return 'placeholder data'
})
}
getData.then(console.log) // placeholder data
getData.then(console.log) //data from DB!
참고로
async
/await
를 사용하여 덜 중첩된(아마도 더 읽기 쉬운) 방식으로 이 코드를 완전히 작성할 수 있습니다. 어느 쪽이든 그다지 강력하게 생각하지 않아서 Promise를 사용했습니다.즐거운 코딩하세요!
Reference
이 문제에 관하여(약속을 포착하여 자리 표시자 데이터 제공), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/annarankin/supplying-placeholder-data-by-catching-promises-372l텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)