Я определяю класс в Javascript, предназначенный для использования в качестве аудиоплеера, совместимого с iOS. Я только начинаю с основ и сталкиваюсь с проблемой при попытке доступа к методу класса.
После создания экземпляра класса (var audio = new WebAudio('soundfile.mp3', document.querySelector(#sound_div)) и попытки доступа к методу audio.playSound() я получаю:
ReferenceError: Can't find variable: elem on line 29
class WebAudio {
constructor(soundFile, elem) {
this.soundFile = soundFile;
this.elem = elem;
}
context() {
var AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
return context;
}
webAudioTouchUnlock(context) {
return new Promise(function (resolve, reject) {
//if AudioContext is suspended, and window has been interacted with
if (context.state === 'suspended' && 'ontouchstart' in window) {
console.info(context.state);
var unlock = function() {
//resume AudioContext (allow playing sound), remove event listeners
context.resume().then(function() {
console.info("context resumed");
this.elem.removeEventListener('touchstart', unlock);
this.elem.removeEventListener('touchend', unlock);
resolve(true);
}, function (reason) {
reject(reason);
});
};
this.elem.addEventListener('touchstart', unlock, false); //error
this.elem.addEventListener('touchend', unlock, false);
} else {
console.info('context not suspended? Context is ' + context.state);
resolve(false);
}
});
}
playSound() {
this.webAudioTouchUnlock(this.context()).then(function (unlocked) {
if (unlocked) {
console.info('playing audio file');
var audio = new Audio('sound/' + soundFile);
if (!audio.playing) {
audio.play();
} else {
audio.pause();
}
}
}, function(reason) {
console.error(reason);
});
document.body.addEventListener('load', playSound(soundFile));
}
}
@JackBashford спасибо за ответ, вопрос об использовании. "var audio = новый WebAudio('soundfile.mp3', document.querySelector(#sound_div)"



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы теряете привязку к this, когда передаете функцию прослушивателю событий:
var unlock = function() {
//resume AudioContext (allow playing sound), remove event listeners
context.resume().then(function() {
console.info("context resumed");
// this won't point to the instance when called by listener
this.elem.removeEventListener('touchstart', unlock);
this.elem.removeEventListener('touchend', unlock);
resolve(true);
}, function (reason) {
reject(reason);
});
};
this.elem.addEventListener('touchstart', unlock, false); //error
Функции стрелок или ручной вызов bind(this) могут это исправить. Функция стрелки будет лексически связывать this в функции, что означает, что this будет значением this, из которого она была определена, а не из того, как она вызывается:
var unlock = () => {
//resume AudioContext (allow playing sound), remove event listeners
context.resume().then(() => {
console.info("context resumed");
this.elem.removeEventListener('touchstart', unlock);
this.elem.removeEventListener('touchend', unlock);
resolve(true);
}, function (reason) {
reject(reason);
});
};
this.elem.addEventListener('touchstart', unlock, false); //error
Спасибо, теперь получаю TypeError: undefined is not a object (оценка this.elem) — webAudio.js:29 — audio.elem содержит правильную ссылку
@froggomad извините, здесь много вложенных функций. Вероятно, вам также нужно определить обратный вызов Promise с помощью функции стрелки: return new Promise((resolve, reject) => {...
Спасибо, вы ведете меня по правильному пути... без вас я бы не справился. Нужен this.webAudioTouchUnlock(this.context()).then( (unlocked) => в playSound() и отдельная функция для добавления слушателя
Круто, рад, что ты понял @froggomad.
Какой пример ввода? Какие аргументы вы бы передали
new WebAudio?