简体   繁体   English

如何等待第三方JavaScript函数返回

[英]How to wait for 3rd party JavaScript function to return

Given the following snippet of code 给出以下代码段

var empowerInstance = null;

function onClick_btnSendMessage() {
    var childIFrame = window.document.getElementById("editorFrame");
    if (!empowerInstance) {
        empowerInstance = EditorAPI.getInstance(childIFrame.contentWindow, window.location.origin);
    }
    empowerInstance.document.hasChanged(hasChangedCallback);
}

function hasChangedCallback(returnValue) {
    console.log("empowerInstance.document.hasChanged = " + returnValue.isDirty);
    if (returnValue.success === true && returnValue.isDirty === true) {
        empowerInstance.document.save(saveCallback);
    }
}

function saveCallback(returnValue) {
    console.log("empowerInstance.document.save = " + returnValue.success);
    if (returnValue.success === false) {
        console.log(returnValue.message);
    }
}

window.addEventListener("DOMContentLoaded", function (event) {
    console.log("DOM fully loaded and parsed");
    if (typeof location.origin === "undefined")
        window.location.origin = window.location.protocol + "//" + window.location.host;
    document.getElementById("btnSendMessage").addEventListener("click", onClick_btnSendMessage);
});

Instead of wiring the button up , I'd like to fire the code from the activation of a Bootstrap tab event. 我不想启动按钮,而是想通过启动Bootstrap选项卡事件来触发代码。

$('a[data-toggle="tab"]').on("shown.bs.tab", function (e) {

    onClick_btnSendMessage(); // Naive way, as this does not wait

    var target = $(e.target).attr("data-EditorUrl"); // activated tab
    var childIFrame = $("#editorFrame");
    childIFrame.attr("src", target);

});

So my question is "How do I wait on this function to complete before changing the source of childIFrame?". 因此,我的问题是“如何在更改childIFrame的源之前等待该功能完成?”。

empowerInstance.document.hasChanged(hasChangedCallback);

I conceptually understand the use of Promises and Callbacks, but writing one that functions correctly is a different story. 我从概念上理解了Promises和Callbacks的用法,但是编写一个功能正确的说法却是另一回事。

UPDATED 更新

This version is refactored to eliminate the button handler, thus improving readability. 对该版本进行了重构,以消除按钮处理程序,从而提高了可读性。

The usage is also important. 用法也很重要。 When the page loads for the first time it is positioned on a tab. 首次加载页面时,它位于选项卡上。 This tab is associated to a document that is hosted in an iFrame. 该标签与在iFrame中托管的文档相关联。 If the user edits this document then tries to change tabs, I'd like to invoke the check for being dirty/save, then once saved, move to the next tab/document. 如果用户编辑此文档,然后尝试更改标签,则我想调用检查是否脏/保存,然后保存后,移至下一个标签/文档。 There is also the case that switching between tabs/documents won't cause a save because the document is not dirty. 在某些情况下,选项卡/文档之间的切换不会导致保存,因为文档不脏。

var empowerInstance = null;

function hasChangedCallback(returnValue) {
    console.log("empowerInstance.document.hasChanged = " + returnValue.isDirty);
    if (returnValue.success === true && returnValue.isDirty === true) {
        empowerInstance.document.save(saveCallback);
    }
}

function saveCallback(returnValue) {
    console.log("empowerInstance.document.save = " + returnValue.success);
    if (returnValue.success === false) {
        console.log(returnValue.message);
    }
}

$(function () {

    if (typeof location.origin === "undefined") {
        window.location.origin = window.location.protocol + "//" + window.location.host;
    }

    $('a[data-toggle="tab"]').on("shown.bs.tab", function (e) {

        var childIFrame = $("#editorFrame");
        if (!empowerInstance) {
            empowerInstance = EditorAPI.getInstance(childIFrame[0].contentWindow, window.location.origin);
        }
        empowerInstance.document.hasChanged(hasChangedCallback);// Need to wait for completion 

        var target = $(e.target).attr("data-EditorUrl"); // activated tab
        childIFrame.attr("src", target);

    });
});

Thank you, Stephen 谢谢斯蒂芬

You can use some higher order functions to do what you want. 您可以使用一些高阶函数来执行所需的操作。 Instead of passing the hasChangedCallback and saveCallback directly to the empowerInstance.document methods, you'll instead invoke a function that returns those callbacks, but also passes along your own callback that you'll call once all the async operations have finally completed. 相反,传递的hasChangedCallbacksaveCallback直接向empowerInstance.document方法,你会改为调用返回的回调函数,而且沿着你自己的回调传递,你会打电话一旦所有的异步操作都终于完成了。 Here's what it'll look like: 外观如下:

$('a[data-toggle="tab"]').on("shown.bs.tab", function (e) {
    var target = $(e.target).attr("data-EditorUrl"); // activated tab

    onClick_btnSendMessage(function () {
        var childIFrame = $("#editorFrame");
        childIFrame.attr("src", target);
    });
});

function onClick_btnSendMessage(myCallback) {
    var childIFrame = window.document.getElementById("editorFrame");
    if (!empowerInstance) {
        empowerInstance = EditorAPI.getInstance(childIFrame.contentWindow, window.location.origin);
    }
    empowerInstance.document.hasChanged(getHasChangedCallback(myCallback));
}

function getHasChangedCallback(myCallback) {
    return function hasChangedCallback(returnValue,  myCallback) {
        console.log("empowerInstance.document.hasChanged = " + returnValue.isDirty);
        if (returnValue.success === true && returnValue.isDirty === true) {
            empowerInstance.document.save(getSaveCallback(myCallback));
        }
    } 
}

function getSaveCallback(myCallback) {
    return function saveCallback(returnValue) {
        console.log("empowerInstance.document.save = " + returnValue.success);
        if (returnValue.success === false) {
            console.log(returnValue.message);
        }

        myCallback && myCallback(); // make sure myCallback isn't null before invoking
    }
}

It's not exactly attractive, but it should get you what you want. 它并不完全吸引人,但它可以为您带来想要的东西。

I've refactored your code to show how this can be done using promises. 我已经重构了您的代码,以展示如何使用Promise做到这一点。

 function onClick_btnSendMessage() { var childIFrame = window.document.getElementById("editorFrame"); if (!empowerInstance) { empowerInstance = EditorAPI.getInstance(childIFrame.contentWindow, window.location.origin); } var doc = empowerInstance.document; return hasChanged(doc).then(function() { return save(doc) }) } function hasChanged(doc) { return new Promise(function(resolve, reject) { doc.hasChanged(function(returnValue) { if (returnValue.success === true && returnValue.isDirty === true) { resolve(returnValue) } else { reject(returnValue) } }) }) } function save(doc) { return new Promise(function(resolve, reject) { doc.save(function(returnValue) { if (returnValue.success === false) { console.log(returnValue.message); reject(returnValue) } else { resolve(returnValue) } }) }) } // ------ $('a[data-toggle="tab"]').on("shown.bs.tab", function(e) { onClick_btnSendMessage().then(function() { var target = $(e.target).attr("data-EditorUrl"); // activated tab var childIFrame = $("#editorFrame"); childIFrame.attr("src", target); }).catch(function(error) { // handle the error console.error('Error!', error) }) }); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在第3方函数javascript中将arrray元素传播到参数中 - Spreading arrray elements into parameters in 3rd party function javascript Javascript:由于第3方,我的setTimeout函数不起作用 - Javascript: My setTimeout function not working because of 3rd party 如何识别哪个第 3 方 flash object 称为 Javascript ZC1C425268E68385D14AB5074C17Z9? - How to identify which 3rd party flash object called a Javascript function? 如何使使异步行为像angular2 http请求的第三方JavaScript函数? - How to make 3rd party javascript function that makes an asynchronous behave like an angular2 http request? 如何在Ember.js模板中注入第三方JavaScript? - How to inject 3rd party javascript in Ember.js template? 如何将第 3 方 javascript 模块“导入”到我的反应项目中? - How to “import” a 3rd party javascript module to my react project? 如何使用emscripten调用第三方JavaScript库? - How do I call a 3rd party javascript library with emscripten? 如何使用嵌入式JavaScript在第三方网站上创建弹出窗口? - How to use embedded javascript to create a popup on 3rd party sites? 如何在AngularJS部分模板中包含第三方JavaScript库? - How to include 3rd party javascript libraries in AngularJS partial template? 如何使用Javascript / JQuery从第三方网站加载XML? - How to load a XML from a 3rd party site with Javascript/JQuery?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM