Javascript: вопрос переменной области - PullRequest
0 голосов
/ 12 сентября 2011

Почему я попадаю в alert вызов undef?

#!/usr/bin/env perl
use warnings;
use 5.014;
use utf8;
use Mojolicious::Lite;
use DBI;

my $db = 'my_test_db.db';
my $table = 'my_test_table';
my $dbh = DBI->connect( "dbi:SQLite:dbname=$db", '', '', 
            { RaiseError => 1, PrintError => 0, AutoCommit => 1, sqlite_unicode => 1, } 
        ) or die $DBI::errstr;
$dbh->do( "CREATE TEMP TABLE $table ( str TEXT, num INTEGER )" );
my $sth = $dbh->prepare( "INSERT INTO  $table ( str, num ) VALUES ( ?, ?)" );
$sth->execute( 'aaa', '111' );
$sth->execute( 'bbb', '222' );
$sth->execute( 'ccc', '333' );

get '/eingabe' => sub {
    my $self = shift;
    $self->render( 'eingabe' );
};

get '/search_db/:col' => sub {
    my $self = shift;
    my $col = $self->param( 'col' );
    my $term = $self->param( 'term' );
    my $sth = $dbh->prepare( "SELECT DISTINCT $col FROM $table WHERE $col LIKE ?" );
    $sth->execute( $term . '%');
    my $ref;
    while ( my $row = $sth->fetchrow_arrayref() ) {
            push @$ref, @$row;
    }
    $self->render( json => $ref );
};

app->start;

__DATA__
@@ eingabe.html.ep
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.js"></script>
<script type="text/javascript">
    $( document ).ready( function() {
        var ids = [ 'str', 'num' ];
        for ( var i = 0; i < ids.length; i++ ){
            $( "#" + ids[i] ).autocomplete({
                source: function( request, response ){ 

                    alert( ids[i] );  // <---

                    $.getJSON( '/search_db/'  + ids[i], request, function( data_from_server ){
                        var suggestions = [];
                        var len = data_from_server.length;
                        for( var i = 0; i < len; i++ ){
                            suggestions.push( data_from_server[i] );
                        }
                        response( suggestions );
                    });
                }
            });
        }
    });
</script>
</head>
<body>
<form>
    <table>
        <tr><td>String:</td><td><input type="text" id="str" name="str"" /></td></tr>
        <tr><td>Number:</td><td><input type="number" id="num" name="num" /></td></tr>
    </table><br />
    <input type="submit" value="OK"/>
</form>
</body>
</html>

Ответы [ 3 ]

3 голосов
/ 12 сентября 2011

Звучит так, как будто вы столкнулись с проблемой, описанной здесь: Создание замыканий в циклах: распространенная ошибка

Причина, по которой вы получаете undefined при вызове alert, заключается в том, что при вызове функции autocomplete ваш цикл for завершил выполнение, означая, что ваша переменная цикла i имеет значение 2 то есть ids.length + 1. Следовательно, ids[i] - это то же самое, что и ids[2], которого не существует, поскольку в вашем массиве ids есть только 2 элемента. Я попытался создать простую демонстрацию этого поведения, чтобы проиллюстрировать, что происходит: http://jsfiddle.net/ianoxley/KwXVs/1/ (для просмотра результатов вам нужно будет открыть консоль браузера).

Если вы создадите дополнительное закрытие, которое должно помочь сохранить ваш прицел и избавиться от undefined (см. http://jsfiddle.net/ianoxley/BVa5Q/).

Если вы попытаетесь изменить свой код на что-то вроде этого, надеюсь, это избавит от проблемы:

$(document).ready(function () {
    function initAutocomplete(element_id) {
        $("#" + element_id).autocomplete({
            source: function (request, response) {

                alert(element_id);  // <---

                $.getJSON('/search_db/' + element_id, request, function (data_from_server) {
                    var suggestions = [];
                    var len = data_from_server.length;
                    for (var i = 0; i < len; i++) {
                        suggestions.push(data_from_server[i]);
                    }
                    response(suggestions);
                });
            }
        });        
    }

    var ids = ['str', 'num'];
    for (var i = 0; i < ids.length; i++) {
        var current_id = ids[i];
        initAutocomplete(current_id);
    }
});

Надеюсь, это поможет.

0 голосов
/ 12 сентября 2011

Ваша функция обратного вызова находится вне области видимости.Когда вы атакуете функцию на ссылку на событие, которая вызывается при срабатывании события после завершения цикла for.

Хорошее правило, когда вы используете обратные вызовы, всегда должно передавать все, чтоэта функция требует или присоединяет все, что требуется к объекту окна, и возвращает его глобально.

0 голосов
/ 12 сентября 2011

Вы дважды определяете итерационную переменную i: она используется внутри вашего обратного вызова для вызова $.getJSON снова.

вам следует переименовать его в другое имя, j (просто пример).

так будет сказано:

$( document ).ready( function() {
    var ids = [ 'str', 'num' ];
    for ( var i = 0; i < ids.length; i++ ){
        $( "#" + ids[i] ).autocomplete({
            source: function( request, response ){ 

                alert( ids[i] );  // <---

                $.getJSON( '/search_db/'  + ids[i], request, function( data_from_server ){
                    var suggestions = [];
                    var len = data_from_server.length;
                    for( var j = 0; j < len; j++ ){
                        suggestions.push( data_from_server[j] );
                    }
                    response( suggestions );
                });
            }
        });
    }
});

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...