#javascript #node.js
#javascript #node.js
Вопрос:
Я прошу прощения, если это неясно, уже поздно, и я не знаю, как лучше всего это объяснить.
Я использую источник события для передачи данных из ответа сервера в функцию внутри отдельного класса в другом файле, но при попытке использовать методы в этих классах this
ключевое слово, очевидно, не работает (потому что в этом сценарии this
ссылается на источник события сервера) — как бы я ссылался на функцию внутри самого класса? Я предоставил код, который поможет немного лучше проиллюстрировать мою точку зрения
ServiceClass.js
class StreamService {
/**
*
* @param {} database
* @param {Collection<Guild>} guilds
*/
constructor (database, guilds,) {
.....
twitchListener.on('live', this.sendLiveAlert) // fire test method when we get a notification
// if there are streamers to monitor, being monitoring
winston.info('Stream service initialized')
}
..............
async get (url, params = null, headers = this.defaultHeaders) {
// check oauth token
const expirationDate = this.token.expires_in || 0
if (expirationDate <= Date.now() || !this.token) await this.getAccessToken()
// build URL
const index = 0
let paramsString = ''
for (const [key, value] of params.entries()) {
if (index === 0) {
paramsString = `?${key}=${value}`
} else {
paramsString = `amp;${key}=${value}`
}
}
const res = await fetch(url paramsString, { method: 'GET', headers: headers })
if (!res.ok) {
winston.error(`Error performing GET request to ${url}`)
return null
}
return await res.json()
}
async sendLiveAlert(streamTitle, streamURL, avatar, userName, gameId, viewerCount, thumbnail, startDateTime) {
// get game name first (no headers needed)
const params = new Map()
params.set('id', gameId)
const gameData = await this.get('https://api.twitch.tv/heliix/games', params, this.defaultHeaders)
if(gameData) {
// get webhook and send message to channel
const webhookClient = new WebhookClient('755641606555697305', 'OWZvI01kUUf4AAIR9uv2z4CxRse3Ik8b0LKOluaOYKmhE33h0ypMLT0JJm3laomlZ05o')
const embed = new MessageEmbed()
.setTitle(`${userName} just went live on Twitch!`)
.setURL(streamURL)
.setThumbnail(avatar)
.addFields(
{ name: 'Now Playing', value: gameData.data[0].name },
{ name: 'Stream Title', value: streamTitle }
)
.setImage(thumbnail)
}
webhookClient.send('Webhook test', embed)
}
}
Server.js
class TwitchWebhookListener extends EventEmitter {
......................
// Routes
server
.post((req, res) => {
console.log('Incoming POST request on /webhooks')
............................
const data = req.body.data[0]
if(!this.streamerLiveStatus.get(data.user_id) amp;amp; data.type === 'live') {
// pass request body to bot for processing
this.emit(
'live',
data.title, // stream title
`https://twitch.tv/${data.user_name}`, // channel link
`https://avatar.glue-bot.xyz/twitch/${data.user_name}`, // streamer avatar
data.user_name,
data.game_id,
data.viewer_count,
data.thumbnail_url,
data.started_at // do we need this?
)
}
break
default:
res.send(`Unknown webhook for ${req.params.id}`)
break
}
} else {
console.log('The Signature did not match')
res.send('Ok')
}
} else {
console.log('It didn't seem to be a Twitch Hook')
res.send('Ok')
}
})
}
}
const listener = new TwitchWebhookListener()
listener.listen()
module.exports = listener
В sendLiveAlert
методе я пытаюсь вызвать метод get класса StreamService — но поскольку он вызывается непосредственно через эмиттер внутри server.js
, this
относится конкретно к Server.js
классу — есть ли какой-либо способ, который я могу использовать StreamService.get()
? Очевидно, я мог бы просто переписать код внутри самого метода, но это кажется ненужным, когда он прямо там?
Ответ №1:
Измените это:
twitchListener.on('live', this.sendLiveAlert)
к этому:
twitchListener.on('live', this.sendLiveAlert.bind(this))
Или вы также могли бы сделать это:
twitchListener.on('live', (...args) => {
this.sendLiveAlert(...args);
});
С помощью .bind()
этого создается оболочка функции, которая сбрасывает правильное значение this
для вас. В случае функции arrow она сохраняет лексическое значение this
для вас.
Комментарии:
1. Одновременные ответы. Я мог бы удалить свою, если вы обработаете
args
в своей функции второго варианта.2. @RahulBhobe — Я добавил аргументы.
3. Это мое воображение или поля между блоками кода и текстом в ответах внезапно увеличились?
4. А, понятно! Я думал, что это проблема с областью видимости, я просто не был уверен, как с этим справиться. Это сработало как шарм!