programing

Ajax 응답에서 반환된 JavaScript 함수 호출

megabox 2023. 2. 11. 09:08
반응형

Ajax 응답에서 반환된 JavaScript 함수 호출

Ajax 명령을 전송하면 함수가 포함된 스크립트 블록을 반환하는 시스템이 있습니다.이 데이터가 DIV에 올바르게 삽입된 후 이 함수를 호출하여 필요한 작업을 수행할 수 있도록 하고 싶습니다.

이게 가능합니까?

이 폼에서 질문을 올바르게 해석하려면 "OK, Ajax는 이미 다 끝냈습니다.DIV에 삽입된 JavaScript 함수가 그 순간부터 언제든지 호출 가능한지 알고 싶을 뿐입니다.즉, 콜백에 대한 문맥상 호출을 하고 싶지 않습니다.

네, 이와 같은 것을 의미하는 경우, 답변은 "예"입니다.다음 조건 하에서 브라우저 내에서 페이지가 지속되는 동안 언제든지 새 코드를 호출할 수 있습니다.

Ajax 1) Ajax는 JavaScript 입니다.
이 2) 에 <script> 블록 의 <div>선언 코드가 실행된 적이 없기 때문에 브라우저는 새로운 함수의 존재를 인식하지 못합니다. 꼭 해야 돼요.eval()새로운 함수를 효과적으로 선언하고 전체 페이지 수명 동안 사용할 수 있도록 하기 위해 Ajax 콜백에 의해 반환되는 선언 코드.

이 코드는 매우 더미라고 해도 그 생각을 설명합니다.

<html>
    <body>
        <div id="div1">
        </div>
        <div id="div2">
            <input type="button" value="Go!" onclick="go()" />
        </div>
        <script type="text/javascript">
            var newsc = '<script id="sc1" type="text/javascript">function go() { alert("GO!") }<\/script>';
            var e = document.getElementById('div1');
            e.innerHTML = newsc;
            eval(document.getElementById('sc1').innerHTML);
        </script>
    </body>
</html>

Ajax는 사용하지 않았지만 컨셉은 동일합니다(선택한 예시는 그다지 스마트하지 않아도 됩니다:-)

일반적으로 말하면, 저는 당신의 솔루션 설계에 의문을 제기하지 않습니다.즉, 함수를 다른 .js 파일로 외부화하고 일반화하는 것이 적절한지 여부입니다.그러나 이러한 솔루션은 특히 Ajax 호출이 반복되어야 하는 경우, 같은 컨텍스트가 기능하는 경우 더 많은 문제를 일으킬 수 있습니다.ld change 또는 선언된 함수의 지속성과 관련된 경우 이 스레드에서 권장되는 예 중 하나로 설계를 변경하는 것을 진지하게 고려해야 합니다.

마지막으로 질문을 잘못 이해하셨다면 Ajax 콜백이 돌아왔을 때 함수의 컨텍스트 호출에 대해 말씀하셨다면 크로스 브라우저, 테스트 완료, 완전한 기능성을 갖춘 krosenvold에서 설명한 프로토타입 접근 방식을 제안하고 싶습니다.이 접근방식은 향후 구현을 위한 보다 나은 로드맵을 제공할 수 있습니다.

주의: eval()은 오용되기 쉽습니다.를 들어, 요구가 서드파티에 의해 대행 수신되어 신뢰할 수 없는 코드가 송신되었다고 합시다.그런 다음 eval()을 사용하면 이 신뢰할 수 없는 코드를 실행할 수 있습니다.평가()위험에 대해서는 여기를 참조하십시오.


반환된 HTML/Ajax/JavaScript 파일 안에는 JavaScript 태그가 있습니다.룬스크립트 같은 아이디를 주세요.이러한 태그에 ID를 추가하는 것은 드물지만 구체적으로 참조할 필요가 있습니다.

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

메인 창에서 새로운 JavaScript 코드 블록(이 경우 runscript라고 부릅니다)만 평가하여 eval 함수를 호출합니다.

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

적어도 Internet Explorer 9와 Google Chrome에서는 동작합니다.

이는 충분히 가능하며, 이에 대한 정당한 사용 사례도 있습니다.프로토타입 프레임워크를 사용하면 다음과 같이 수행됩니다.

new Ajax.Updater('items', '/items.url', {
    parameters: { evalJS: true}
});

Ajax 업데이트 프로그램에 대한 설명서를 참조하십시오.옵션은 공통 옵션 세트에 있습니다."this"가 가리키는 위치에 대해서는 평소처럼 몇 가지 주의사항이 있으므로 자세히 읽어보십시오.

JavaScript 드 java java java java java 。에 함수가 되어 있는 myFunc(), 하면 요.myFunc()follows maybe. 아마 과 같이예요.아마도 다음과 같다.

if (window["myFunc"])
   myFunc()

함수가 존재하는지 여부를 확인합니다.Internet Explorer 6에서 작동하는 더 나은 크로스 브라우저 방법이 있을 수 있습니다.

코드에는 다소 이상한 디자인으로 보입니다.일반적으로 함수를 .js 파일에서 직접 호출한 후 Ajax 호출로만 데이터를 가져오는 것이 더 합리적입니다.

단, 구문적으로 올바른 JavaScript 코드라면 응답에 대해 eval()을 호출하여 동작해야 한다고 생각합니다.

jQuery에서는 getScript를 사용합니다.

아래 방법으로 ajax를 통해 함수를 만든다면...

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

...val을 통해 실행하면 컨텍스트에 문제가 발생할 수 있습니다.이것을 콜백 함수로 합니다.

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

함수 내에서 함수를 선언하게 되므로 이 새 함수는 해당 범위에서만 액세스할 수 있습니다.

이 시나리오에서 글로벌함수를 작성하는 경우는, 다음과 같이 선언할 수 있습니다.

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

하지만 난 네가 이걸 하면 안 된다고 생각해.

실수하게 해서 죄송합니다...

jQuery에는 코드를 전체적으로 평가할 수 있는 평가 기능이 있어 컨텍스트상의 문제를 해소할 수 있습니다.이 함수는 globalEval()이라고 불리며 제 목적에 맞게 잘 작동했습니다.이 문서의 설명서는 여기에서 찾을 수 있습니다.

jQuery API 설명서에서 제공되는 코드 예를 다음에 나타냅니다.

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

test();
// newVar === true

이 기능은 외부 스크립트를 동적으로 로드할 때 매우 유용합니다.

이러한 작업을 수행하기 위한 체크리스트:

  1. 반환된 Ajax 응답이 평가(ed)됩니다.
  2. 는 【형식】으로 선언되어 있다.func_name = function() {...}

또한 프로토타입과 같이 이를 처리하는 프레임워크를 사용하는 것이 좋습니다.당신은 가지고 있다Ajax.updater.

PHP 사이드 코드 파일 클래스의 이름입니다.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()"/>

이제 로컬 스크립트.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
                  }


        });
}

이 코드도 동작합니다.대신 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);
}

평소 사용하는 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아이디, 아약스, 아이디, 아이약스.
url【ajax】【URL】【다】
busyMsg대상 요소의 임시 텍스트가 됩니다.
finishCB아약스
에서 xhr.onreadystatechange = function() {...}<script>아약스★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★이치노

제가 이걸 테스트해봤는데 효과가 있어요.문제가 뭐죠?javascript 요소 안에 새로운 함수를 넣고 호출하기만 하면 됩니다.그건 작동할 것이다.

이건 좋은 생각이 아닌 것 같아.

Ajax 메서드에 의해 반환된 데이터에서 JavaScript 코드의 나머지 부분에 포함할 함수를 추출해야 합니다.

그러나 스크립트 블록에 작성된 인라인 스크립트 방식도 사용할 수 있습니다(또한 스크립트 블록을 div에 삽입하는 이유를 이해할 수 없습니다.

저는 여기서 제공되는 모든 기술을 시도해 보았지만, 마지막으로 동작하는 방법은 JavaScript 함수를 발생해야 할 페이지/파일에 넣고 단순히 함수로서 Ajax의 응답 부분에서 호출하는 것이었습니다.

...
}, function(data) {
    afterOrder();
}

이게 첫 번째 시도에서 먹혔기 때문에 공유하기로 했습니다.

오늘 응답 HTML 하단에 JavaScript를 배치하여 이 문제를 해결했습니다.

오버레이에 표시된 HTML을 많이 반환하는 AJAX 요청이 있었습니다.반환된 응답 HTML/오버레이의 버튼에 클릭 이벤트를 첨부해야 했습니다.보통 페이지에서는 자바스크립트를 "window.onload" 또는 "$(document)"로 래핑합니다.ready"는 새로운 오버레이용 DOM이 렌더링된 후 이벤트 핸들러를 DOM 오브젝트에 연결하지만, 이것은 새로운 페이지 로드가 아닌 AJAX 응답이었기 때문에 브라우저는 내 JavaScript를 실행하지 않았고, 내 이벤트 핸들러는 DOM 요소에 접속되지 않았으며, 내 새로운 기능의 일부도 실행되지 않았다."$(document)"를 사용하지 않고 "AJAX 응답 문제에서 JavaScript 실행"을 해결했습니다.[ready] (준비완료)를 선택합니다.단, 문서 끝에 JavaScript를 배치하고 HTML/DOM이 렌더링된 후 실행되도록 합니다.

AJAX 스크립트를 실행하는 데 몇 밀리초 이상 걸리는 경우, eval()은 항상 먼저 실행되어 빈 응답 요소를 평가한 후 실행하려는 스크립트로 AJAX를 채웁니다.

타이밍이나 평가()를 조작하는 것이 아니라, 여기에서는 대부분의 상황에서 효과가 있을 뿐만 아니라, 아마 조금 더 안전할 수 있는 간단한 회피책이 있습니다.일반적으로 eval()을 사용하는 것은 코드로 평가되는 문자는 클라이언트 측에서 쉽게 조작할 수 있기 때문에 꺼려집니다.

개념.

  1. 메인 페이지에 javascript 기능을 포함합니다.동적 요소를 인수로 받아들일 수 있도록 작성합니다.
  2. AJAX 파일에서 공식 DOM 이벤트(클릭, 온포커스, 온블러, 온로드 등)를 사용하여 함수를 호출합니다.응답의 다른 요소에 따라서는, 심리스하게 느껴질 수 있습니다.동적 요소를 인수로 전달합니다.
  3. 응답 요소가 채워지고 이벤트가 발생하면 함수가 실행됩니다.

이 예에서는 요소가 페이지에 추가된 후 jquery-ui 라이브러리에서 AJAX 요소에 동적 자동 완성 목록을 첨부합니다.쉽죠?

start.discloss.disclossible

<!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>

Ajax request.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";
?>

이 작업을 하기 위해 뭔가 필요한 것이 있었습니다.이 작업은 오랫동안 유효했습니다.많은 솔루션 중 하나로 여기에 게시되어 있습니다.jQuery를 사용하지 않고 다음 함수를 사용하면 도움이 될 수 있습니다.스크립트 태그가 있는 HTML 전체를 전달하면 해석 및 실행할 수 있습니다.

function parseScript(_source) {
    var source = _source;
    var scripts = new Array();

    // Strip out tags
    while(source.indexOf("<script") > -1 || source.indexOf("</script") > -1) {
        var s = source.indexOf("<script");
        var s_e = source.indexOf(">", s);
        var e = source.indexOf("</script", s);
        var e_e = source.indexOf(">", e);

        // Add to scripts array
        scripts.push(source.substring(s_e+1, e));
        // Strip from source
        source = source.substring(0, s) + source.substring(e_e+1);
        }

        // Loop through every script collected and eval it
        for(var i=0; i<scripts.length; i++) {
        try {
        if (scripts[i] != '')
        {
        try  {          //IE
            execScript(scripts[i]);
        }
        catch(ex)           //Firefox
        {
            window.eval(scripts[i]);
        }

        }
        }
        catch(e) {
           // do what you want here when a script fails
           if (e instanceof SyntaxError) console.log (e.message+' - '+scripts[i]);
        }
        }
        // Return the cleaned source
        return source;
}

Federico Zancan의 답변은 맞지만 스크립트에 ID를 부여하고 모든 스크립트를 평가할 필요는 없습니다.함수 이름만 평가하면 호출할 수 있습니다.

이를 위해 프로젝트에서는 Ajax 응답 내에서 반환된 함수를 호출하는 프록시 함수를 작성했습니다.

function FunctionProxy(functionName){
    var func = eval(functionName);
    func();
}

언급URL : https://stackoverflow.com/questions/510779/calling-a-javascript-function-returned-from-an-ajax-response

반응형