等待多个事件

时间:2012-12-19 20:39:15

标签: javascript javascript-events

我目前正在开发一款主要用于自我教育目的的应用程序,因为我还没有完全习惯于js,我可以为我的问题使用一些帮助:

在我的应用程序中,我使用的是javascript库(jqMobi),用于DOM操作,页面转换,ajax调用等,我还使用phonegap访问设备功能,例如地理定位。

当我启动我的应用程序时,我想获取设备的地理位置,向我的服务器发送ajax(jsonp)请求(包括设备的地理位置),该请求返回我将用于构建的json对象数组列表。

在我获得地理位置之前,我需要等待加载电话空白。在使用jqMobi进行ajax调用并处理响应之前,我需要等待它加载。

所以我基本上要听事件

document.addEventListener("DOMContentLoaded",execute_this,false);  //jqMobi is now ready
document.addEventListener("deviceready", execure_sth, false); //Phonegap is now ready

如果这两个事件都被触发而不是之前,我该如何执行一个函数?

如果我使用jQuery,我会使用它的$ .Deferred对象及其When ... Then Function但由于我无权访问这些,我正在寻找替代方案。

提前感谢您的帮助!

5 个答案:

答案 0 :(得分:19)

乍一看,这样的事情肯定会奏效:

var executed_this = false, executed_sth = false;

function execute_this() {
  executed_this = true;
  combined_execution();
}

function execute_sth() {
  executed_sth = true;
  combined_execution();
}

function combined_execution() {
  if (executed_this && executed_sth) {
    // magic!
  }
}

但是不可扩展(如果你想要第三个事件等待怎么办?)。计数器可以工作:

var wait_on = 2;

function execute_this() {
  combined_execution();
}

function execute_sth() {
  combined_execution();
}

function combined_execution() {
  wait_on--;
  if (wait_on === 0) {
    // magic!
  }
}

更具可扩展性,但假设事件只触发一次。无论哪种方式,这些都是能够控制你所要求的流量控制类型的主要因素,而其他一切(在大多数情况下)都是这两者的更高层次的抽象。

答案 1 :(得分:2)

试试这个,

document.addEventListener("DOMContentLoaded",execute_this,false);
function execute_this(){
document.addEventListener("deviceready", execure_sth, false);
}
function execute_sth(){
//your code here
}

答案 2 :(得分:0)

您可以做出在事件触发时解决的承诺,并等待它们都准备就绪。

var dcl = new Promise(function(resolve) {
    document.addEventListener("DOMContentLoaded",resolve,false);
})
var deviceready = new Promise(function(resolve) {
    document.addEventListener("deviceready", resolve, false);
})

Promise.all([dcl, deviceready]).then(function() {
    //both are ready
});

答案 3 :(得分:0)

将这里的一些答案合并到waitForEvents(eventTarget, eventNames);

用法:

waitForEvents(window, 'DOMContentLoaded,deviceready').then(function() {
    // do stuff
});

来源:

/**
 * Wait for multiple DOM events to fire
 * @param {object} eventTarget - element to listen for events on (default document)
 * @param {Array<string>|string} eventNames - array or csv string of event names
 * @returns {Promise<Array>} resolves with array of event objects
 */
function waitForEvents(eventTarget, eventNames) {

    eventTarget = eventTarget || document;
    eventNames = (!Array.isArray(eventNames)) ? String(eventNames).split(',') : eventNames;

    // clean event names
    eventNames = eventNames.map(function(item) {
        return String(item).trim();
    })
    .filter(function(item) {
        return item !== '';
    });

    var items = [];

    // create a promise to wait for each event
    var listeners = eventNames.map(function(eventName) {
        return new Promise(function(resolve) {
            eventTarget.addEventListener(eventName, function(e) {
                items.push(e);
                resolve();
            }, false);
        });
    });

    // resolve once all events have fired
    return Promise.all(listeners).then(function() {
        return Promise.resolve(items);
    });
}

要点 GitHub

答案 4 :(得分:0)

Promise.all 是要走的路,但为了好玩(以及导入 polyfill 的懒惰),我想出了这个小解决方案:


executedCount = 0

function onExecuted() {
    document.body.dispatchEvent(new Event('executedCountIs'+(++executedCount)));
}

function execute_this() {
    onExecuted()
}

function execute_sth() {
    onExecuted()
}

function main() {
    document.body.addEventListener('executedCountIs2', doStuffWhenBothAreReady)
    execute_this()
    execute_sth()
}

我假设 Javascript 引擎在此处保护我免受竞争条件的影响。