[英]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. 相反,传递的
hasChangedCallback
和saveCallback
直接向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.