14

我目前正在开发一个主要用于自学目的的应用程序,由于我还没有完全习惯 js,所以我可以为我的问题提供一些帮助:

在我的应用程序中,我使用了一个用于 DOM 操作、页面转换、ajax 调用等的 Javascript 库 (jqMobi),并且我还使用 phonegap 来访问设备功能,例如地理位置。

当我启动我的应用程序时,我想获取设备的地理位置,向我的服务器发送一个 ajax (jsonp) 请求(包括设备的地理位置),它返回一个 JSON 对象数组,我将使用这些对象来建立一个列表.

在获得地理位置之前,我需要等待 phonegap 加载。在使用 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 函数,但由于我无法访问这些,我正在寻找替代方案。

4

5 回答 5

25

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

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

更具可扩展性,但假设事件只触发一次。无论哪种方式,这些都是可以控制您所要求的流控制类型的原语,而其他一切(在大多数情况下)都是对这两者的更高级别的抽象。

于 2012-12-19T20:44:34.417 回答
15

你可以让 Promise 在事件触发时解决,并等待它们都准备好。

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
});
于 2019-07-09T00:30:47.793 回答
1

尝试这个,

document.addEventListener("DOMContentLoaded",execute_this,false);
function execute_this(){
document.addEventListener("deviceready", execure_sth, false);
}
function execute_sth(){
//your code here
}
于 2012-12-19T20:44:21.920 回答
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 引擎在这里保护我免受竞争条件的影响。

于 2021-05-11T14:11:05.237 回答
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 上的要点

于 2021-02-07T14:41:05.553 回答