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
이 기능은 외부 스크립트를 동적으로 로드할 때 매우 유용합니다.
이러한 작업을 수행하기 위한 체크리스트:
- 반환된 Ajax 응답이 평가(ed)됩니다.
- 는 【형식】으로 선언되어 있다.
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()을 사용하는 것은 코드로 평가되는 문자는 클라이언트 측에서 쉽게 조작할 수 있기 때문에 꺼려집니다.
개념.
- 메인 페이지에 javascript 기능을 포함합니다.동적 요소를 인수로 받아들일 수 있도록 작성합니다.
- AJAX 파일에서 공식 DOM 이벤트(클릭, 온포커스, 온블러, 온로드 등)를 사용하여 함수를 호출합니다.응답의 다른 요소에 따라서는, 심리스하게 느껴질 수 있습니다.동적 요소를 인수로 전달합니다.
- 응답 요소가 채워지고 이벤트가 발생하면 함수가 실행됩니다.
예
이 예에서는 요소가 페이지에 추가된 후 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
'programing' 카테고리의 다른 글
잭슨을 사용하여 Kotlin 컬렉션을 역직렬화하는 방법 (0) | 2023.02.11 |
---|---|
다른 파일에서의 Angularjs 라우팅 (0) | 2023.02.11 |
다이내믹 ID ng-module (0) | 2023.02.11 |
max File Size를 설정하려고 하는데 허용되지 않습니다. (0) | 2023.02.11 |
value Change Listener 또는 f:ajax 리스너를 사용하는 경우 (0) | 2023.02.11 |