AJAX js из загруженной части страницы не работает [дубликат]

Когда ваши пути include разные

Ошибки компоновщика могут произойти, если заголовочный файл и связанная с ним общая библиотека (файл .lib) не синхронизируются. Позволь мне объяснить.

Как работают линкеры? Линкер соответствует объявлению функции (объявленному в заголовке) с его определением (в общей библиотеке) путем сравнения их подписи. Вы можете получить ошибку компоновщика, если компоновщик не найдет определение функции, которое идеально подходит.

Возможно ли получить ошибку компоновщика, даже если объявление и определение, похоже, совпадают? Да! Они могут выглядеть одинаково в исходном коде, но это действительно зависит от того, что видит компилятор. По сути, вы можете столкнуться с такой ситуацией:

// header1.h
typedef int Number;
void foo(Number);

// header2.h
typedef float Number;
void foo(Number); // this only looks the same lexically

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

Вы можете спросить, как это получается в такой ситуации? Включите пути, конечно! Если при компиляции разделяемой библиотеки путь include приводит к header1.h, и вы в конечном итоге используете header2.h в своей собственной программе, вы оставите царапины на своем заголовке, задаваясь вопросом, что произошло (каламбур).

Пример того, как это может произойти в реальном мире, объясняется ниже.

Дальнейшая разработка с примером

У меня есть два проекта: graphics.lib и main.exe. Оба проекта зависят от common_math.h. Предположим, что библиотека экспортирует следующую функцию:

// graphics.lib    
#include "common_math.h" 

void draw(vec3 p) { ... } // vec3 comes from common_math.h

И затем вы идете вперед и включаете библиотеку в свой собственный проект.

// main.exe
#include "other/common_math.h"
#include "graphics.h"

int main() {
    draw(...);
}

Boom! Вы получаете ошибку компоновщика, и вы понятия не имеете, почему она терпит неудачу. Причина в том, что общая библиотека использует разные версии одного и того же include common_math.h (я сделал это очевидным здесь в этом примере, включив другой путь, но это может быть не всегда так очевидно. Возможно, путь include отличается в настройки компилятора).

Обратите внимание, что в этом примере компоновщик сказал бы вам, что не смог найти draw(), когда на самом деле вы знаете, что он явно экспортируется библиотекой. Вы могли часами царапать себе голову, думая, что пошло не так. Дело в том, что компоновщик видит другую подпись, потому что типы параметров немного отличаются. В этом примере vec3 является другим типом в обоих проектах в отношении компилятора. Это может произойти из-за того, что они происходят из двух немного разных файлов include (возможно, включенные файлы поступают из двух разных версий библиотеки).

Отладка компоновщика

DUMPBIN - ваш друг, если вы используете Visual Studio. Я уверен, что другие компиляторы имеют другие подобные инструменты.

Процесс выглядит следующим образом:

  1. Обратите внимание на странное искаженное имя, указанное в ошибке компоновщика. (например, draw @ graphics @ XYZ).
  2. Выгрузите экспортированные символы из библиотеки в текстовый файл.
  3. Найдите экспортированный символ, представляющий интерес, и обратите внимание, что искаженное имя
  4. Обратите внимание на то, почему искаженные имена оказались разными. Вы могли бы видеть, что типы параметров различны, хотя они выглядят одинаково в исходном коде.
  5. Причина, почему они разные. В приведенном выше примере они различаются из-за разных файлов include.

[1] По проекту я имею в виду набор исходных файлов, которые связаны друг с другом для создания либо библиотеки, либо исполняемого файла .

РЕДАКТИРОВАТЬ 1: Переписать первый раздел, который будет легче понять. Пожалуйста, прокомментируйте ниже, чтобы сообщить мне, нужно ли что-то еще исправлять. Спасибо!

62
задан Federico Zancan 13 September 2013 в 09:40
поделиться

12 ответов

Ответ Federico Zancan верен, но вам не нужно указывать свой скрипт ID и оценивать весь ваш скрипт. Просто оцените свое имя функции и его можно вызвать.

Чтобы достичь этого в нашем проекте, мы написали прокси-функцию для вызова функции, возвращаемой внутри ответа Ajax.

function FunctionProxy(functionName){
    var func = eval(functionName);
    func();
}
70
ответ дан Community 24 August 2018 в 08:32
поделиться

Я решил это сегодня, поставив свой JavaScript в нижней части ответа HTML.

У меня был запрос AJAX, который возвратил кучу HTML, который был отображен в оверлее. Мне нужно было прикрепить событие click к кнопке в возвращаемом ответе HTML / overlay. На обычной странице я обернул бы свой JavaScript в «window.onload» или «$ (document) .ready», чтобы он привязал обработчик события к объекту DOM после того, как DOM для нового наложения был визуализирован, но потому что это был ответ AJAX, а не новая загрузка страницы, это событие никогда не происходило, браузер никогда не выполнял мой JavaScript, мой обработчик событий никогда не привязывался к элементу DOM, и моя новая функциональность не работала. Опять же, я решил «выполнить JavaScript в проблеме ответа AJAX», не используя «$ (document) .ready» в начале документа, но, разместив свой JavaScript в конце документа и выполнив его после HTML / DOM.

0
ответ дан Andrew Koper 24 August 2018 в 08:32
поделиться

Я хотел бы добавить, что в jQuery есть функция eval, позволяющая вам глобально оценить код, который должен избавить вас от любых контекстуальных проблем. Эта функция называется globalEval () , и она отлично работает для моих целей. Его документация может быть найдена здесь здесь .

Это пример кода, предоставленного документацией jQuery API:

function test()
{
  jQuery.globalEval("var newVar = true;")
}

test();
// newVar === true

Эта функция чрезвычайно полезна, когда она приходит к загрузке внешних скриптов динамически, которые вы, по-видимому, пытались сделать.

3
ответ дан beta 24 August 2018 в 08:32
поделиться

Примечание: eval () можно легко использовать неправильно, скажем, что запрос перехвачен третьей стороной и отправляет вам не доверенный код. Затем с помощью eval () вы будете запускать этот недопустимый код. См. Здесь опасности eval () .


Внутри возвращаемого файла HTML / Ajax / JavaScript у вас будет тег JavaScript. Дайте ему идентификатор, например runningcript . Необязательно добавлять идентификатор к этим тегам, но это необходимо для ссылки на него.

<script type="text/javascript" id="runscript">
    alert("running from main");
</script>

В главном окне вызывается функция eval, оценивая только этот НОВЫЙ блок кода JavaScript (в этом case, он называется runningcript ):

eval(document.getElementById("runscript").innerHTML);

И он работает, по крайней мере, в Internet & nbsp; Explorer & nbsp; 9 и Google Chrome.

39
ответ дан commonSenseCode 24 August 2018 в 08:32
поделиться

Просто помните, если вы создаете функцию ниже, используя ajax ...

function foo()
{
    console.log('foo');
}

... и выполняйте ее через eval, вы, вероятно, столкнетесь с проблемой контекста. Возьмите это как функцию обратного вызова:

function callback(result)
{
    responseDiv = document.getElementById('responseDiv');
    responseDiv.innerHTML = result;
    scripts = responseDiv.getElementsByTagName('script');
    eval(scripts[0]);
}

Вы будете объявлять функцию внутри функции, поэтому эта новая функция будет доступна только в этой области.

Если вы хотите чтобы создать глобальную функцию в этом сценарии, вы можете объявить ее следующим образом:

window.foo = function ()
{
    console.log('foo');
};

Но я также думаю, что вы не должны этого делать ...

Извините за любая ошибка здесь ...

3
ответ дан Daniel Hartmann 24 August 2018 в 08:32
поделиться

С jQuery я бы сделал это с помощью getScript

4
ответ дан kgiannakakis 24 August 2018 в 08:32
поделиться

Это кажется довольно странным дизайном для вашего кода - обычно имеет смысл использовать ваши функции непосредственно из файла .js, а затем извлекать данные только с помощью вызова Ajax.

Однако, я что он должен работать, вызвав eval () ответ - при условии, что это синтаксически правильный код JavaScript.

6
ответ дан Peter Mortensen 24 August 2018 в 08:32
поделиться

Моя обычная функция вызова ajax:

function xhr_new(targetId, url, busyMsg, finishCB)
{
    var xhr;

    if(busyMsg !== undefined)
        document.getElementById(targetId).innerHTML = busyMsg;

    try { xhr = new ActiveXObject('Msxml2.XMLHTTP'); }
    catch(e)
    {
        try { xhr = new ActiveXObject('Microsoft.XMLHTTP'); }
        catch(e2)
        {
            try { xhr = new XMLHttpRequest(); }
            catch(e3) { xhr = false; }
        }
    }

    xhr.onreadystatechange = function()
    {
        if(xhr.readyState == 4)
        {
            if(xhr.status == 200)
            {
                var target = document.getElementById(targetId)
                target.innerHTML = xhr.responseText;
                var scriptElements = target.getElementsByTagName("script");
                var i;
                for(i = 0; i < scriptElements.length; i++)
                    eval(scriptElements[i].innerHTML);
                if(finishCB !== undefined)
                    finishCB();
            }
            else
                document.getElementById(targetId).innerHTML = 'Error code: ' + xhr.status;
        }
    };

    xhr.open('GET', url, true);
    xhr.send(null);
    // return xhr;
}

Некоторое объяснение: targetId - это идентификатор элемента (обычно div), где будет выводиться текст результата вызова ajax. url - адрес вызова ajax. busyMsg будет временным текстом в целевом элементе. finishCB вызывается, когда операция ajax завершена успешно. Как вы видите в xhr.onreadystatechange = function() {...} все элементы <script> будут собраны из ответа ajax и будут выполняться один за другим. Кажется, он работает очень хорошо для меня. Два последних параметра являются необязательными.

1
ответ дан Ray 24 August 2018 в 08:32
поделиться

Код стороны PHP Имя файла class.sendCode.php

<?php
class  sendCode{ 

function __construct($dateini,$datefin) {

            echo $this->printCode($dateini,$datefin);
        }

    function printCode($dateini,$datefin){

        $code =" alert ('code Coming from AJAX {$this->dateini} and {$this->datefin}');";
//Insert all the code you want to execute, 
//only javascript or Jquery code , dont incluce <script> tags
            return $code ;
    }
}
new sendCode($_POST['dateini'],$_POST['datefin']);

Теперь со страницы Html вы должны запустить функцию ajax для отправки данных.

....  <script src="http://code.jquery.com/jquery-1.9.1.js"></script> ....
Date begin: <input type="text" id="startdate"><br>
Date end : <input type="text" id="enddate"><br>
<input type="button" value="validate'" onclick="triggerAjax()"/>

Теперь в нашем локальном script.js мы определим ajax

function triggerAjax() {
    $.ajax({
            type: "POST",
            url: 'class.sendCode.php',
            dataType: "HTML",
            data : {

                dateini : $('#startdate').val(),
                datefin : $('#enddate').val()},

                  success: function(data){
                      $.globalEval(data);
// here is where the magic is made by executing the data that comes from
// the php class.  That is our javascript code to be executed
                  }


        });
}
2
ответ дан Sultanos 24 August 2018 в 08:32
поделиться

Если ваш сценарий AJAX занимает больше пары миллисекунд для запуска, eval () будет всегда запускаться вперед и оценивать пустой элемент ответа до того, как AJAX заполнит его сценарием, который вы пытаетесь выполнить.

Вместо того, чтобы сбрасывать тайм-аут и eval (), вот довольно простой обходной путь, который должен работать в большинстве ситуаций и, вероятно, немного более безопасен. Использование eval (), как правило, неодобрительно, потому что символы, которые оцениваются как код, легко могут быть обработаны на стороне клиента.

Концепция

  1. Включите функцию javascript на главной странице. Запишите его так, чтобы любые динамические элементы могли быть приняты в качестве аргументов.
  2. В вашем файле AJAX вызовите функцию, используя официальное событие DOM (onclick, onfocus, onblur, onload и т. Д.). В зависимости от того, что другое элементы в вашем ответе, вы можете стать довольно умными, чтобы заставить себя чувствовать себя без проблем. Передайте свои динамические элементы в качестве аргументов.
  3. Когда ваш элемент ответа заполняется и происходит событие, функция запускается.

Пример

В этом примере я хочу добавить динамический список автозаполнения из библиотеки jquery-ui в элемент AJAX ПОСЛЕ того, как элемент был добавлен на страницу. Легко, правда?

start.php

<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
<!-- these libraries are for the autocomplete() function -->
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/ui-lightness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script type="text/javascript">
<!--
// this is the ajax call
function editDemoText(ElementID,initialValue) {
    try { ajaxRequest = new XMLHttpRequest();
    } catch (e) {
    try { ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
    try { ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (e) {
    return false;
    }}}
    ajaxRequest.onreadystatechange = function() {
        if ( ajaxRequest.readyState == 4 ) {
            var ajaxDisplay = document.getElementById('responseDiv');
            ajaxDisplay.innerHTML = ajaxRequest.responseText;
            }
        }
    var queryString = "?ElementID="+ElementID+"&initialValue="+initialValue;
    ajaxRequest.open("GET", "ajaxRequest.php"+queryString, true);
    ajaxRequest.send(null);
    }

// this is the function we wanted to call in AJAX, 
// but we put it here instead with an argument (ElementID)
function AttachAutocomplete(ElementID) {
    // this list is static, but can easily be pulled in from 
    // a database using PHP. That would look something like this:
    /*
     * $list = "";
     * $r = mysqli_query($mysqli_link, "SELECT element FROM table");
     * while ( $row = mysqli_fetch_array($r) ) {
     *    $list .= "\".str_replace('"','\"',$row['element'])."\",";
     *    }
     * $list = rtrim($list,",");
     */
    var availableIDs = ["Demo1","Demo2","Demo3","Demo4"];
    $("#"+ElementID).autocomplete({ source: availableIDs });
    }
//-->
</script>
</head>
<body>
<!-- this is where the AJAX response sneaks in after DOM is loaded -->
<!-- we're using an onclick event to trigger the initial AJAX call -->
<div id="responseDiv"><a href="javascript:void(0);" onclick="editDemoText('EditableText','I am editable!');">I am editable!</a></div>
</body>
</html>

ajaxRequest.php

<?php
// for this application, onfocus works well because we wouldn't really 
// need the autocomplete populated until the user begins typing
echo "<input type=\"text\" id=\"".$_GET['ElementID']."\" onfocus=\"AttachAutocomplete('".$_GET['ElementID']."');\" value=\"".$_GET['initialValue']."\" />\n";
?>
0
ответ дан Typel 24 August 2018 в 08:32
поделиться

Я тестировал это, и он работает. В чем проблема? Просто поместите новую функцию внутри своего javascript-элемента, а затем вызовите ее. Он будет работать.

0
ответ дан user 24 August 2018 в 08:32
поделиться

Этот код работает, а вместо eval html я собираюсь добавить скрипт в голову

function RunJS(objID) {
//alert(http_request.responseText);
var c="";
var ob = document.getElementById(objID).getElementsByTagName("script");
for (var i=0; i < ob.length - 1; i++) {
    if (ob[i + 1].text != null) 
       c+=ob[i + 1].text;
}
var s = document.createElement("script");
s.type = "text/javascript";
s.text = c;
document.getElementsByTagName("head")[0].appendChild(s);
}
0
ответ дан user2054758 24 August 2018 в 08:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: