source

변수가 정의되지 않은 동안 - 대기

factcode 2023. 8. 17. 21:55
반응형

변수가 정의되지 않은 동안 - 대기

나는 있습니다click처음으로 다른 위치에서 자동으로 트리거되는 이벤트입니다.문제는 필요한 변수가 여전히 플래시 및 웹 서비스에 의해 정의되고 있기 때문에 너무 빨리 실행된다는 것입니다.그래서 저는 지금 다음과 같은 것을 가지고 있습니다.

(function ($) {
    $(window).load(function(){
        setTimeout(function(){
            $('a.play').trigger("click");
        }, 5000);
    });
})(jQuery);

문제는 인터넷 연결이 느린 사람의 경우 5초가 너무 빠를 수 있고, 반대로 인터넷 연결이 빠른 사람의 경우 5초가 너무 느릴 수 있다는 것입니다.

그럼 다음 시간까지 지연 또는 제한 시간을 어떻게 해야 합니까?someVariable정의되었습니까?

다음은 찾을 때까지 일부 변수를 계속 찾습니다.0.25초마다 확인합니다.

function waitForElement(){
    if(typeof someVariable !== "undefined"){
        //variable exists, do what you want
    }
    else{
        setTimeout(waitForElement, 250);
    }
}

async, await구현, @Toprak의 답변보다 개선

(async() => {
    console.log("waiting for variable");
    while(!window.hasOwnProperty("myVar")) // define the condition as you like
        await new Promise(resolve => setTimeout(resolve, 1000));
    console.log("variable is defined");
})();
console.log("above code doesn't block main function stack");

OP의 질문을 다시 검토한 후.실제로 의도된 것을 구현하는 더 나은 방법이 있습니다: "변수 집합 콜백".아래 코드는 원하는 변수가 다음과 같이 선언되지 않고 객체(또는 창)에 의해 캡슐화될 경우에만 작동합니다.let또는var 첫 을 남겼습니다 (원문을 읽지 않고 그대로 답을 남겼습니다.)

let obj = encapsulatedObject || window;
Object.defineProperty(obj, "myVar", {
    configurable: true,
    set(v){
        Object.defineProperty(obj, "myVar", {
            configurable: true, enumerable: true, writable: true, value: v });
        console.log("window.myVar is defined");
    }
});
    

Object.defineProperty를 참조하거나 es6 프록시 사용(오버킬일 수 있음)


더 필요한 경우:

/**
 * combining the two as suggested by @Emmanuel Mahuni,
 * and showing an alternative to handle defineProperty setter and getter
 */


let obj = {} || window;
(async() => {
  let _foo = await new Promise(res => {
    Object.defineProperty(obj, "foo", { set: res });
  });
  console.log("obj.foo is defined with value:", _foo);
})();
/*
IMPORTANT: note that obj.foo is still undefined
the reason is out of scope of this question/answer
take a research of Object.defineProperty to see more
*/

// TEST CODE

console.log("test start");
setTimeout(async () => {
  console.log("about to assign obj.foo");
  obj.foo = "Hello World!";
  // try uncomment the following line and compare the output
  // await new Promise(res => setTimeout(res));
  console.log("finished assigning obj.foo");
  console.log("value of obj.foo:", obj.foo); // undefined
  // console: obj.foo is defined with value: Hello World!
}, 2000);

이 코드를 선호합니다.

function checkVariable() {

   if (variableLoaded == true) {
       // Here is your next action
   }
 }

 setTimeout(checkVariable, 1000);

저는 다음과 같은 간단한 것을 선호합니다.

function waitFor(variable, callback) {
  var interval = setInterval(function() {
    if (window[variable]) {
      clearInterval(interval);
      callback();
    }
  }, 200);
}

예제 인 그런다예변함사용니다합께와 함께 합니다.someVariable:

waitFor('someVariable', function() {
  // do something here now that someVariable is defined
});

다양한 조정 작업을 수행할 수 있습니다.의 위서에서setInterval콜, 통과했습니다.200간격 함수가 실행되는 빈도입니다.변수를 확인하기 전에 해당 시간(~200ms)의 지연이 발생하기도 합니다. 어떤 경우에는 지연이 없도록 바로 확인하는 것이 좋습니다.

Ecma Script 2017을 사용하면 비동기 대기 및 함께 사용하여 이를 수행할 수 있습니다. 프로그램이 충돌하거나 잠기지 않는 동안에도 변수는 절대 참이 아닙니다.

//First define some delay function which is called from async function
function __delay__(timer) {
    return new Promise(resolve => {
        timer = timer || 2000;
        setTimeout(function () {
            resolve();
        }, timer);
    });
};

//Then Declare Some Variable Global or In Scope
//Depends on you
let Variable = false;

//And define what ever you want with async fuction
async function some() {
    while (!Variable)
        await __delay__(1000);

    //...code here because when Variable = true this function will
};
////////////////////////////////////////////////////////////
//In Your Case
//1.Define Global Variable For Check Statement
//2.Convert function to async like below

var isContinue = false;
setTimeout(async function () {
    //STOPT THE FUNCTION UNTIL CONDITION IS CORRECT
    while (!isContinue)
        await __delay__(1000);

    //WHEN CONDITION IS CORRECT THEN TRIGGER WILL CLICKED
    $('a.play').trigger("click");
}, 1);
/////////////////////////////////////////////////////////////

또한 이 경우 setTimeout을 사용할 필요가 없습니다. 준비 기능을 비동기식으로 만들기만 하면 됩니다.

다음을 사용할 수 있습니다.

var refreshIntervalId = null;
refreshIntervalId = setInterval(checkIfVariableIsSet, 1000);

var checkIfVariableIsSet = function()
{
    if(typeof someVariable !== 'undefined'){
        $('a.play').trigger("click");
        clearInterval(refreshIntervalId);
    }
};

변수가 설정될 때까지 기다리는 모든 논리가 프로그램이 수행해야 하는 다른 모든 작업을 수행하는 콜백을 호출하는 함수로 지연되는 예가 있습니다. 다른 작업을 수행하기 전에 변수를 로드해야 하는 경우, 이것은 깔끔한 방법처럼 느껴지기 때문에 변수 로드를 다른 모든 작업과 분리합니다.'다른 모든 것'은 기본적으로 콜백임을 보장합니다.

var loadUser = function(everythingElse){
    var interval = setInterval(function(){
      if(typeof CurrentUser.name !== 'undefined'){
        $scope.username = CurrentUser.name;
        clearInterval(interval);
        everythingElse();
      }
    },1);
  };

  loadUser(function(){

    //everything else

  });

Windows 로드 이벤트를 사용하는 대신 문서에서 준비 이벤트를 사용합니다.

$(document).ready(function(){[...]});

이는 완전히 로드된 미디어 콘텐츠를 포함하여 DOM의 모든 것이 준비될 때 실행됩니다.

단축 방법:

   var queue = function (args){
      typeof variableToCheck !== "undefined"? doSomething(args) : setTimeout(function () {queue(args)}, 2000);
};

인수를 전달할 수도 있습니다.

@dnuttle의 답변에 찬성표를 던졌지만 결국 다음과 같은 전략을 사용하게 되었습니다.

// On doc ready for modern browsers
document.addEventListener('DOMContentLoaded', (e) => {
  // Scope all logic related to what you want to achieve by using a function
  const waitForMyFunction = () => {
    // Use a timeout id to identify your process and purge it when it's no longer needed
    let timeoutID;
    // Check if your function is defined, in this case by checking its type
    if (typeof myFunction === 'function') {
      // We no longer need to wait, purge the timeout id
      window.clearTimeout(timeoutID);
      // 'myFunction' is defined, invoke it with parameters, if any
      myFunction('param1', 'param2');
    } else {
      // 'myFunction' is undefined, try again in 0.25 secs
      timeoutID = window.setTimeout(waitForMyFunction, 250);
    }
  };
  // Initialize
  waitForMyFunction();
});

그것은 테스트되고 작동합니다!;)

요지: https://gist.github.com/dreamyguy/f319f0b2bffb1f812cf8b7cae4abb47c

Object.defineProperty(window, 'propertyName', {
    set: value => {
        this._value = value;
        // someAction();
    },
    get: () => this._value
});

또는 이 속성을 함수에 인수로 전달하고 글로벌 개체에 정의할 필요가 없는 경우에도 사용할 수 있습니다.

Object.defineProperty(window, 'propertyName', { set: value => someAction(value) })

그러나 예제에서는 노드를 만들 때 작업을 수행하려는 것처럼 보이므로 MutationObservers를 살펴보시기를 제안합니다.

저는 @dnuttle을 사용하여 답을 수정할 것을 제안합니다.

Try-catch 블록을 사용하면 실행하려는 코드의 일부라도 실패하면 전체 블록이 실패한다는 장점이 있습니다.저는 이것이 여러분에게 일종의 거래를 제공하기 때문에 유용하다고 생각합니다. 모든 것이 이루어지거나 아무것도 이루어지지 않습니다.

외부 요인으로 인해 무한 루프로 끝날 수 있는 코드를 작성해서는 안 됩니다.Ajax 요청의 응답을 기다리고 있는데 서버가 응답하지 않는 경우 바로 이와 같습니다.문제가 있는 루프에 대해 시간을 초과하는 것이 좋습니다.

let time = 0; // Used to keep track of how long the loop runs
function waitForElement() {
  try {
    // I'm testing for an element, but this condition can be
    // any reasonable condition
    if (document.getElementById('test') === null) {
      throw 'error';
    }

    // This is where you can do something with your variable
    // document.getElementById('test').addEventListener....
    // or call a function that uses your value

  } catch (error) {
    // Loop stops executing if not successful within about 5 seconds
    if (time > 5000) {
      // I return false on failure so I can easily check for failure
      return false;
    } else {
      // Increment the time and call the function again
      time += 250;
      setTimeout(waitForElement, 250);
    }
  }
}

// Call the function after the definition, ensures that time is set
waitForElement();

완료되면 플래시가 기능을 호출하도록 할 수 있습니다.웹 서비스가 무슨 뜻인지 잘 모르겠습니다.Ajax를 통해 웹 서비스를 호출하는 JavaScript 코드가 있다고 가정합니다. 이 경우 언제 종료되는지 알 수 있습니다.의 경우,할 수 .setTimeout약 100ms마다 확인할 수 있습니다.

변수가 되어 있는지 는 그냥 그리변다같고인니하 수 는 다 것 과 습 음 은 확 를 여 부 정 지 는 가 의 었 되 ▁be ▁and 다 니 같 ▁just ▁for 습 ▁is ▁check ▁theif (myVariable)또는 더 안전:if(typeof myVariable == "undefined")

제가 이 질문에 몇 년이나 늦었다는 것을 압니다. 많은 사람들이 시간 초과 경로를 선택했습니다. 만약 변수를 정의하는 코드에 접근할 수 없다면, 그것이 아마도 가장 쉬운 방법일 것입니다.

하지만, OP는 그것이 모두 그들만의 코드라고 제안합니다.이 경우 창 객체가 변수를 정의하기를 문자 그대로 기다릴 것이 아니라 변수가 정의되면 이벤트를 발송하여 리소스를 불필요하게 낭비하지 않도록 하는 것이 좋다고 생각합니다.

정의 코드

window.someVariable = 'foo';
const ev = new Event( 'someVariableDefined' );
document.dispatchEvent( ev );

듣기 코드

const triggerClick = () => {
    // cleanup
    document.removeEventListener( 'someVariableDefined', triggerClick, false );
    $('a.play').trigger("click");
}

if( !!window.someVariable ){
    triggerClick();
} else {
    document.addEventListener( 'someVariableDefined', triggerClick, false );
}
while (typeof myVar == void(0)) {
  if ( typeof myVar != void(0)) {
        console.log(myVar);
  }
}

이렇게 하면 변수가 아직 선언되지 않은 경우에만 정의되지 않은 연산자 유형이 사용됩니다.자바스크립트의 모든 유형에 적용 가능해야 합니다.

언급URL : https://stackoverflow.com/questions/7307983/while-variable-is-not-defined-wait

반응형