2017-05-06 55 views
0

鑑於代碼如何等待第三方JavaScript函數返回

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); 
}); 

下面的代碼片段取而代之接線扣的,我想從一個引導標籤事件的激活火的代碼。

$('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); 

}); 

所以我的問題是「如何在更改childIFrame源之前等待此功能完成?」。

empowerInstance.document.hasChanged(hasChangedCallback); 

我概念瞭解使用承諾和回調的,但是寫一個功能正常是一個不同的故事。

更新

此版本重構,以消除該按鈕的處理程序,從而提高可讀性。

用法也很重要。當頁面第一次加載時,它位於選項卡上。此選項卡與託管在iFrame中的文檔相關聯。如果用戶編輯此文檔,然後嘗試更改制表符,我想調用檢查髒/保存,然後一旦保存,移動到下一個標籤/文檔。還有一種情況是,標籤/文檔之間的切換不會導致保存,因爲文檔不髒。

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); 

    }); 
}); 

謝謝 斯蒂芬

+0

我不完全理解你的代碼還沒有,但回答你的問題一般是「用一個回調函數」。 – 4castle

+0

您可以使用回調函數或承諾。所有瀏覽器都不支持Promise,因此您可以使用webpack或babel來完成此操作。 –

回答

1

我重構了您的代碼,以顯示如何使用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) 
 
    }) 
 

 

 
});

+0

我不知道拒絕的用法是否正確,我唯一能想到的是他們會被使用,如果有一個錯誤被困住了。 –

+0

@StephenPatten取決於你的用例。就我個人而言,我認爲如果保存操作失敗,代表此操作的承諾應該被拒絕,但如果您願意,您可以解決承諾。 – thedude

+0

應該明確了,保存中的拒絕是正確的,但是在else塊中hasChanged是尷尬的,那就意味着我們不叫保存。如果我不正確地理解使用情況,我是這個東西的小菜很抱歉 –

1

你可以使用一些higher order functions做你想做什麼。而不是將hasChangedCallbacksaveCallback直接傳遞給empowerInstance.document方法,而是調用一個返回這些回調函數的函數,同時也傳遞您自己的回調函數,一旦所有異步操作最終完成,就會調用它。下面是它會是什麼樣子:

$('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 
    } 
} 

這不完全吸引人,但它應該得到你想要的東西。

+0

非常接近!看起來好像目標值始終設置爲第一個選項卡,並且在此之後永遠不會更改 –

+0

奇數。 e.target的值是否改變?也許'data-EditorUrl'屬性的值在異步事件發生時被更改?嘗試在回調之外移動'target'賦值。我會編輯我的答案來反映。 – bmceldowney

+0

是的,e.target每次點擊該選項卡時都會更改。我試過它沒有編輯(骯髒的錯誤)和編輯(骯髒的真實)相同的行爲。 –