Обработчик ответа сервера вне класса
Есть класс Search который обращается к серверу и возвращает результат. Обращение к серверу висит на событии input. Как можно обработать конкретный ответ (например xxx) вне класса Search.
Из идей это повесить промис на свойство result, но ожидаемо выполниться один раз, а нужно что бы при каждом совпадении.
Можно ли сделать это как то иначе?
Что бы быть уверенным, в том что обработан именно последний запрос использую this.query_id != query_id, но не нравиться что это используется в трех местах. Как можно исправить?
Хотел использовать AbortController, но он отменяет выполнение всех подписанных на него.
UPD:
Можно передавать обработчик в метод init(fn) или свойство result сделать объектом и обернуть его в прокси, что будет правильнее?
function makeid() {
var text = "";
var possible = "abcdefghijklmnopqrstuvwxyz";
for (var i = 0; i < 3; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
text += Math.floor(Math.random() * (99999 - 10000)) + 10000;
return text;
}
class Search {
search_field = document.getElementById('search');
search_mirror = document.getElementById('mirror');
query_id;
result;
constructor() { }
init() {
this.result = new Promise((resolve) => {
this.search_field.oninput = this.runSearch.bind(this, resolve);
});
}
runSearch(resolve) {
if (this.search_field.value.length < 0) return false;
const url = `https://httpbin.org/post`;
const query_id = makeid();
this.query_id = query_id;
fetch(url, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: this.search_field.value
})
}).then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw new Error("ERR-167: Ошибка соединения с сервером!");
}
}).then(
(result) => {
if (this.query_id != query_id) return true;
let res = result.json.message;
this.search_mirror.innerText = res;
if (res == 'xxx') resolve(res);
},
(err) => {
if (this.query_id != query_id) return true;
console.error(err);
}
).finally(() => {
if (this.query_id != query_id) return true;
console.log('done');
});
}
}
let search = new Search();
search.init();
search.result.then(
res => {
alert('goal');
console.log(res);
}
);
<input type="text" value="" id="search" placeholder="xxx">
<div id="mirror"></div>
Ответы (1 шт):
UPD: Можно передавать обработчик в метод init(fn) или свойство result сделать объектом и обернуть его в прокси, что будет правильнее?
Не уверен насчет правильности данного решения, тк. ответ обрабатывается все равно в классе Search, но обработчик можно задать из вне
function makeid() {
var text = "";
var possible = "abcdefghijklmnopqrstuvwxyz";
for (var i = 0; i < 3; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
text += Math.floor(Math.random() * (99999 - 10000)) + 10000;
return text;
}
class Search {
search_field = document.getElementById('search');
search_mirror = document.getElementById('mirror');
query_id;
result = {
data: {},
handler: false
};
constructor() {
this.result = new Proxy(this.result, {
set(target, prop, val, receiver) {
if (prop == 'data' && target.handler instanceof Function) target.handler(val);
return Reflect.set(target, prop, val, receiver);
},
});
}
init() {
this.search_field.oninput = this.runSearch.bind(this);
}
runSearch(resolve) {
if (this.search_field.value.length < 0) return false;
const url = `https://httpbin.org/post`;
const query_id = makeid();
this.query_id = query_id;
fetch(url, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: this.search_field.value
})
}).then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw new Error("ERR-167: Ошибка соединения с сервером!");
}
}).then(
(result) => {
if (this.query_id != query_id) return true;
let res = result.json.message;
this.search_mirror.innerText = res;
if (res == 'xxx') this.result.data = res;
},
(err) => {
if (this.query_id != query_id) return true;
console.error(err);
}
).finally(() => {
if (this.query_id != query_id) return true;
console.log('done');
});
}
}
let search = new Search();
search.init();
search.result.handler = result => {
alert('goal');
console.log(result);
};
<input type="text" value="" id="search" placeholder="xxx">
<div id="mirror"></div>