Демо ниже - это созданная мной функция мгновенного поиска, как и поиск в 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;
        }
    }

}


?>
1
ryanpika 13 Фев 2016 в 02:14
3
Ваши сообщения заполняются в разное время и возвращаются не по порядку. вам нужно подумать о реализации задержки, прежде чем функция onkeyup сработает.
 – 
Shockwave
13 Фев 2016 в 02:19
Спасибо, не могли бы вы быть более конкретными, если возможно, вы могли бы написать какой-нибудь псевдокод для формулировки? А что значит пост возвращается из строя?
 – 
ryanpika
13 Фев 2016 в 02:21
 – 
Shockwave
13 Фев 2016 в 02:25
Если вы не против использования библиотеки, в jquery ui также есть виджет автозаполнения: api.jqueryui. ru / autocomplete
 – 
Shockwave
13 Фев 2016 в 02:27

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.

Я уверен, что вы знаете, что делаете, но я хочу убедиться, что любой, кто увидит этот вопрос, поймет, что уступка в пользу чего-то вроде мгновенного поиска.

2
Nate I 15 Фев 2016 в 00:58
Не могли бы вы подробно объяснить логику, если есть время. Большое спасибо, я немного новичок в javascript.
 – 
ryanpika
13 Фев 2016 в 03:07
Обязательно обновлю ответ прямо сейчас! Извините за задержку.
 – 
Nate I
15 Фев 2016 в 00:46
Я хотел бы также отметить, что решение, предоставленное gion_13, было бы отличным в сочетании с моим решением выше. Вы можете установить таймер на что-то меньшее, например, 300-500 миллисекунд (настройте по своему вкусу) и связать его с ответом gion_13, чтобы получить действительно быстрый мгновенный поиск, который не попадет в базу данных с ошибочными / устаревшими вызовами.
 – 
Nate I
15 Фев 2016 в 23:32

Вы должны учитывать две вещи: отклонить ваши вызовы и отменить все предыдущие запросы ajax.

Для первого есть много информации о методах устранения дребезга / дросселирования. По сути, вы должны гарантировать, что не выполняете более одного вызова функции (searchq) за определенный период времени. Таким образом, если пользователь наберет abc, это не вызовет 3 разных поиска: a, ab и abc. Вместо этого будет запущен единичный поиск всего результата (abc).

Еще одна вещь, которую вы должны учитывать, - это прерывание неразрешенных вызовов ajax.
Поскольку вы полагаетесь на вызовы ajax для отображения результатов, и поскольку вызовы ajax ... ну ... асинхронны, на самом деле у вас не должно быть нескольких одновременных вызовов ajax. Возьмем следующий пример:

  1. типы пользователей ab
  2. функция searchq выполняется для первого символа (a)
  3. функция searchq выполняется для новой последовательности (ab)
  4. обещание ajax для второго вызова разрешается
  5. обещание ajax для первого вызова разрешается
  6. пользователь видит результат из-за неправильного ввода

Чтобы избежать этой проблемы, вы должны прервать - или, по крайней мере, проигнорировать - любой другой вызов ajax, который выполняется к моменту запуска нового.

1
gion_13 13 Фев 2016 в 02:30