运行一个每50毫秒调用一次的函数,并在条件为真时返回值

时间:2015-05-13 08:47:50

标签: javascript

我想要一个能够知道某个html元素是否存在的代码。 我在超时内使用递归调用。 也许可以成为另一种方法,但我有兴趣知道如何编写这段代码。

if (exist("an_id")!==null)
{ ..... }

function exist (id)
{ times =20;
  var el;
 function get_el (callback) 
 { 
    el =  document.getElementById(_id);      
    if (el==null )
    {
           if (--times==0) 
           callback();     
           else
            setTimeout( function () {get_el()}, 50);
    }
    else
    callback();
 }
 get_el ( function (){return el;}); // first call. pass callback.
}

此代码显然运行良好,' el'在'时间后检测到或不检测到指定,但功能存在'没有回报什么。

我有些困惑。任何帮助将不胜感激.-

2 个答案:

答案 0 :(得分:2)

好吧,你不能只使用return value of a synchronous method。您的情况总是评估为假。

您可以将其封装在一个返回promise或接受回调的函数中:

function exists(id){
    return new Promise(function(resolve, reject){ // old browsers need polyfill
        setTimeout(function check(){ 
           if(document.getElemenyById(id)) resolve();
           else setTimeout(check, 50);
        }, 50);
    });
}

可以让你这样做:

exists("someID").then(function(){
   // here the element exists
});

答案 1 :(得分:0)

好吧,你确实说过你有兴趣找到如何以你的方式编写代码,所以我做了一些修改,但试图让它尽可能地与你的代码保持一致。

我所做的最相关的更改是将回调传递给exist而不是get_el。这样,回调函数“保持活动”,直到递归超时完成。但是,您需要在回调中运行“this element exists”代码,因为这是“异步”。

我也改变了一些缩进/加法大括号,因为你的代码对我来说很困惑:

http://jsfiddle.net/bro2nvtz/4/

function exist(id, callback) {
    var times = 20;
    var el;
    // Added some more console longs and additional calls to `callback`
    // so it's easy to keep track of what's going on
    function get_el() {
        el = document.getElementById(id);
        if (!el) {
            console.log("Trying... " + times);
            callback(el);
            if (--times == 0) {
                console.log("Giving up...");
                callback(el);
            } else {
                setTimeout(function() {
                    get_el()
                }, 50);
            }
        } else {
            console.log("Found it!");
            callback(el);
        }
    }
    get_el();
}
// The way you were doing things, the callback was only getting passed once, and then, it was undefined.
// I think it's a better idea to pass it to the `exist` function, so that it persists as long as
// the timeout is still running.
// For some reason, you were also using _id instead of id. Typo?
exist('dinosaur', function(el) {
  
    // Inside of this callback, run the code that you wish to run
    // when the element exists (or when it doesn't).
    console.log( 'Is it there?: ' + (el ? 'yes! id: ' + el.id : 'no') );
  
    // If it exists...
    if(el) {
      console.log("+------------------------------+");
      console.log("I know for sure it exists, yay!");
      console.log("+------------------------------+");
      setTimeout(function () { 
        el.style.opacity = '1';
      }, 200);
    }
  
    window.scrollTo(0, document.body.scrollHeight);
  
});

// For testing...
// Logger and a timeout that appends the img after 500ms

(function () {
    var old = console.log;
    var logger = document.getElementById('log');
    console.log = function (message) {
        if (typeof message == 'object') {
            logger.innerHTML += (JSON && JSON.stringify ? JSON.stringify(message) : message) + '<br />';
        } else {
            logger.innerHTML += message + '<br />';
        }
    }
})();

// Creates and appends an img of id `dinosaur` to the body, after 500ms.
// Increase the timeout to something like 5000ms and your script will give up.
setTimeout(function () {
    var dinosaur = document.createElement('img');
    dinosaur.id = 'dinosaur';
    dinosaur.src = 'http://www.enchantedlearning.com/tgifs/Trexskelanim.gif';
    dinosaur.style.cssText = 'opacity: 0; transition: all 500ms;';
    document.body.appendChild(dinosaur);
}, 750);
html, body {
    background: #000;
}
pre {
    line-height: 1.5em;
    color: lightblue;
}
<pre id="log"></pre>