Демо ниже - это созданная мной функция мгновенного поиска, как и поиск в Google, которая выводит результат сразу после ввода пользователя.
При тестировании он работает плавно на локальном хосте, но в Интернете он работает с запаздыванием, то есть, когда пользователь быстро вводит несколько символов, нажатие клавиши не будет отображаться в поле ввода в течение нескольких секунд, чтобы дождаться обработки данных (я думаю), а затем набранные символы отобразились через много секунд после этого. Абсолютно это не очень хорошо для пользователя. Как я могу это решить?
Внешний интерфейс
<input onkeyup="searchq();" type="text">
<script>
function searchq(){
// get the value
txt = $("input").val();
// post the value
if(txt){
$.post("search.php", {searchVal: txt}, function(result){
$("#search_output").html(result+"<br><a class='anchor_tag_s' href='createobject.php?object="+txt+"'><div id='notfound'>Not found above? Create Here.</div><a>");
});
}
else{
$("#search_output").html("");
}
};
</script>
Backend
//query the search using match
$query=mysqli_query($conn,"SELECT * from objects WHERE Match(name) Against ('%$search%' in natural language mode) LIMIT 9") or die("could not search! Oops, Panpan might be hacked");
$count=mysqli_num_rows($query);
//if match no result using like query
if($count==0){
$query=mysqli_query($conn,"SELECT * from objects WHERE name LIKE '%$search%' LIMIT 9") or die("could not search! Oops, Panpan database might be hacked");
$count=mysqli_num_rows($query);
if ($count==0){
while($count==0){
//if matach and like show no result, remove the frist word of array, then search, if no result, do it again, if not, do it again.
$search = explode(" ",$search);
$search=array_slice($search,1,2);
$search=implode(" ",$search);
$query=mysqli_query($conn,"SELECT * from objects WHERE name LIKE '%$search%' LIMIT 9") or die("could not search! Oops, Panpan database might be hacked");
$count=mysqli_num_rows($query);
while($row=mysqli_fetch_assoc($query)){
$object_id=$row["object_id"];
$object_name=$row["name"];
$object_description=$row["description"];
$object_up=$row["up"];
$object_down=$row["down"];
$object_views=$row["views"];
$output=$object_name;
$result= "<a class='anchor_tag_s' href='"."object.php?id=".$object_id."'><div>".$output."</div></a>";
echo $result;
}
}
}
else{
// print out the like query
while($row=mysqli_fetch_assoc($query)){
$object_id=$row["object_id"];
$object_name=$row["name"];
$object_description=$row["description"];
$object_up=$row["up"];
$object_down=$row["down"];
$object_views=$row["views"];
$output=$object_name;
$result= "<a class='anchor_tag_s' href='"."object.php?id=".$object_id."'><div>".$output."</div></a>";
echo $result;
}
}
}
else{
// print out the match query
while($row=mysqli_fetch_assoc($query)){
$object_id=$row["object_id"];
$object_name=$row["name"];
$object_description=$row["description"];
$object_up=$row["up"];
$object_down=$row["down"];
$object_views=$row["views"];
$output=$object_name;
$result= "<a class='anchor_tag_s' href='"."object.php?id=".$object_id."'><div>".$output."</div></a>";
echo $result;
}
}
}
?>
2 ответа
Я бы посоветовал абсолютно не искать прямо при нажатии клавиши. Это невероятно неэффективно и требует больших ресурсов. Я бы посоветовал установить таймер, скажем, на одну секунду. Затем, при включении, вы обновляете этот таймер до одной секунды. Если он когда-либо достигнет 0, затем выполните поиск. Что-то вроде этого:
timer = 1000;
started = false;
$("input[type=text]").keyup( function(){
window.timer = 1000;
if(window.started == false) queueTimer();
window.started = true;
});
function queueTimer(){
if(window.timer <= 0){
//Timer has run out, business logic here!
searchq();
window.started = false;
} else {
window.timer -= 100;
setTimeout(queueTimer, 100);
}
}
Установите таймер на любое значение в миллисекундах. Я рекомендую одну секунду, но вы можете уменьшить ее по своему усмотрению.
Проверьте скрипку здесь:
https://jsfiddle.net/kbyy2m6u/
Что делает код
Сразу же мы установили таймер на 1000 миллисекунд и started
на false
.
Встроенная функция keyup
сбрасывает таймер на 1000 миллисекунд, ставит таймер в очередь и устанавливает started
на true
. Мы устанавливаем его на true
, чтобы функция queueTimer()
не ставилась в очередь несколько раз (что свело бы на нет всю точку постановки в очередь мгновенных поисков). Если для него установлено значение true
, оно не будет запускаться queueTimer()
до тех пор, пока не истечет таймер и пока не будет проведен поиск.
queueTimer()
- это хлеб с маслом здесь. Если таймер еще не закончился, он просто уменьшит значение переменной timer
на 100 миллисекунд и вызовет себя для повторного запуска через 100 миллисекунд (цикл до истечения таймера). Когда он заканчивается, он выполняет ваш searchq()
и снова устанавливает для started
значение false
, чтобы мгновенный поиск можно было запустить еще раз.
Проще говоря, каждый раз, когда кто-то вводит текст в поле поиска, он будет ждать одну секунду, прежде чем выполнять мгновенный поиск. Таймер сбрасывается при нажатии клавиши, даже после запуска очереди, так что во время набора текста человек не будет искать. Это предотвращает множественные ошибочные поиски, гарантируя, что пользователь приостановил на некоторое время, чтобы действительно провести поиск.
Теперь небольшое предостережение
Google - гигант - они делают волшебные вещи в сети. Такие вещи, как мгновенный поиск, хороши в теории, но для тех из нас, кто не может вложить миллиарды долларов в исследования и разработки, как Google, это то, что обычно не стоит головной боли.
Каждый звонок в базу данных требует больших затрат. Если в вашем веб-приложении есть другие функции, которые обращаются к базе данных, и теперь вы добавляете мгновенный поиск, будьте готовы к некоторым довольно интересным побочным эффектам. Они могут даже быть непредвиденными побочными эффектами для совершенно разных баз данных из-за блокировок данных на вашем MySQL Engine . Это одна из причин, почему блокировка данных так распространена во многих установках Magento.
Я уверен, что вы знаете, что делаете, но я хочу убедиться, что любой, кто увидит этот вопрос, поймет, что уступка в пользу чего-то вроде мгновенного поиска.
Вы должны учитывать две вещи: отклонить ваши вызовы и отменить все предыдущие запросы ajax.
Для первого есть много информации о методах устранения дребезга / дросселирования. По сути, вы должны гарантировать, что не выполняете более одного вызова функции (searchq
) за определенный период времени. Таким образом, если пользователь наберет abc
, это не вызовет 3 разных поиска: a
, ab
и abc
. Вместо этого будет запущен единичный поиск всего результата (abc
).
Еще одна вещь, которую вы должны учитывать, - это прерывание неразрешенных вызовов ajax.
Поскольку вы полагаетесь на вызовы ajax для отображения результатов, и поскольку вызовы ajax ... ну ... асинхронны, на самом деле у вас не должно быть нескольких одновременных вызовов ajax. Возьмем следующий пример:
- типы пользователей
ab
- функция
searchq
выполняется для первого символа (a
) - функция
searchq
выполняется для новой последовательности (ab
) - обещание ajax для второго вызова разрешается
- обещание ajax для первого вызова разрешается
- пользователь видит результат из-за неправильного ввода
Чтобы избежать этой проблемы, вы должны прервать - или, по крайней мере, проигнорировать - любой другой вызов ajax, который выполняется к моменту запуска нового.
Похожие вопросы
Связанные вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript/JS) и его различных диалектах/реализациях (кроме ActionScript). Обратите внимание, что JavaScript — это НЕ Java. Включите все теги, относящиеся к вашему вопросу: например, [node.js], [jQuery], [JSON], [ReactJS], [angular], [ember.js], [vue.js], [typescript], [стройный] и т. д.