замените getRecord
на это
function getRecord(cell_date) {
return $.ajax({
url: 'rec/getRecord/'+cell_date,
type: 'get',
dataType: 'json'
}).then(function(response){
console.log("getRecord response: "+JSON.stringify(response));
return response['data'];
});
}
И удалите оба ключевых слова async
и await
из любого места в вашем коде, кроме testAsyncAwaitFunction
в этих двух частях:
[ 1111] async function testAsyncAwaitFunction()
и
let cellRecord = await getRecord(cell_date);
В противном случае они вам не нужны.
Раньше это не работало, потому что ваша функция должна возвращать обещание, содержащее данные. Вы должны прочитать об обещаниях JavaScript . Async / Await является в значительной степени синтаксическим сахаром для них и используется для обработки асинхронного кода. Единственный действительный асинхронный код, который у вас есть, это вызов getRecord
.
Вот то, что наконец работало на меня:
public bool WebPageLoaded
{
get
{
if (this.WebBrowser.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
return false;
if (this.HtmlDomDocument == null)
return false;
// iterate over all the Html elements. Find all frame elements and check their ready state
foreach (IHTMLDOMNode node in this.HtmlDomDocument.all)
{
IHTMLFrameBase2 frame = node as IHTMLFrameBase2;
if (frame != null)
{
if (!frame.readyState.Equals("complete", StringComparison.OrdinalIgnoreCase))
return false;
}
}
Debug.Print(this.Name + " - I think it's loaded");
return true;
}
}
На завершенном событии каждого документа я работаю на основе всего элемента HTML и проверяю все доступные кадры (я знаю, что это может быть оптимизировано). Для каждого кадра я проверяю его состояние готовности. Это довольно надежно, но точно так же, как jeffamaphone сказал, что я уже видел сайты, которые инициировали некоторые внутренние обновления. Но вышеупомянутый код удовлетворяет мои потребности.
Править: каждый кадр может содержать кадры в нем так, я думаю, что этот код должен быть обновлен для рекурсивной проверки состояния каждого кадра.
Как насчет того, чтобы использовать JavaScript в каждом кадре для установки флага, когда кадр полон, и затем имеет C#, смотрят на флаги?
У меня нет альтернативы для Вас, но интересно если IsBusy
свойство быть tru
e во время Документа Полный обработчик - то, потому что обработчик все еще работает и поэтому WebBrowser
управление технически все еще 'занято'.
Простое решение состояло бы в том, чтобы иметь цикл, который выполняет каждые 100 мс или поэтому до IsBusy
флаг сбрасывается (с макс. временем выполнения в случае ошибок). Это, конечно, принимает это IsBusy
не будет установлен на false
в любой точке во время загрузки страницы.
Если Документ, который Полный обработчик подписывает на другом потоке, Вы могли бы использовать блокировку для отправки основного потока, чтобы спать и разбудить его из Документа Полный поток. Затем проверьте IsBusy
флаг, повторно блокируя основной поток является все еще true
.
Я не уверен, что это будет работать, но пытаться добавить JavaScript "onload" событие на Вашем frameset как этот:
function everythingIsLoaded() { alert("everything is loaded"); }
var frameset = document.getElementById("idOfYourFrameset");
if (frameset.addEventListener)
frameset.addEventListener('load',everythingIsLoaded,false);
else
frameset.attachEvent('onload',everythingIsLoaded);
Можно ли использовать jQuery? Затем Вы могли легко связать кадр готовые события на целевых кадрах. См. этот ответ для направлений. Это сообщение в блоге также имеет дискуссию об этом. Наконец существует плагин, который Вы могли использовать.
Идея состоит в том, что Вы считаете количество кадров в использовании веб-страницы:
$("iframe").size()
и затем Вы рассчитываете, сколько раз было запущено iframe готовое событие.
Вы получите событие BeforeNavigate и DocumentComplete для внешней веб-страницы, а также каждый кадр. Вы знаете, что сделаны, когда Вы получаете событие DocumentComplete для внешней веб-страницы. Необходимо смочь использовать управляемый equivilent IWebBrowser2:: TopLevelContainer () для определения этого.
Остерегайтесь, однако, сам веб-сайт может инициировать больше навигации кадра каждый раз, когда он хочет, таким образом, Вы никогда не знаете, сделана ли страница действительно навсегда. Лучшее, которое можно сделать, проводят подсчет всего BeforeNavigates, Вы видите и постепенно уменьшаете количество, когда Вы получаете DocumentComplete.
Править: Вот управляемые документы: TopLevelContainer.
Мой подход к тому, чтобы сделать что-то , когда страница полностью загружена (включая кадры), это что-то подобное:
using System.Windows.Forms;
protected delegate void Procedure();
private void executeAfterLoadingComplete(Procedure doNext) {
WebBrowserDocumentCompletedEventHandler handler = null;
handler = delegate(object o, WebBrowserDocumentCompletedEventArgs e)
{
ie.DocumentCompleted -= handler;
Timer timer = new Timer();
EventHandler checker = delegate(object o1, EventArgs e1)
{
if (WebBrowserReadyState.Complete == ie.ReadyState)
{
timer.Dispose();
doNext();
}
};
timer.Tick += checker;
timer.Interval = 200;
timer.Start();
};
ie.DocumentCompleted += handler;
}
Из моих других подходов я узнал несколько «не« не »:
System.timers.timer
вместо Windows.Forms.timer
, странные ошибки начнутся в странных местах, если вы сделаете, из-за таймера Различная поток, что остальное ваше приложение. Вот как я решил проблему в моем приложении:
private void wbPost_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url != wbPost.Url)
return;
/* Document now loaded */
}
Я просто использую метод webBrowser.StatusText. Когда он говорит «Готово», все загружается! Или мне чего-то не хватает?
Вот моя протестированная версия. Просто сделайте это своим обработчиком событий DocumentCompleted
и поместите код, который вы хотите вызывать только один раз , в метод OnWebpageReallyLoaded ()
. Фактически, этот подход определяет, когда страница была стабильной в течение 200 мс, а затем делает свое дело.
// event handler for when a document (or frame) has completed its download
Timer m_pageHasntChangedTimer = null;
private void webBrowser_DocumentCompleted( object sender, WebBrowserDocumentCompletedEventArgs e ) {
// dynamic pages will often be loaded in parts e.g. multiple frames
// need to check the page has remained static for a while before safely saying it is 'loaded'
// use a timer to do this
// destroy the old timer if it exists
if ( m_pageHasntChangedTimer != null ) {
m_pageHasntChangedTimer.Dispose();
}
// create a new timer which calls the 'OnWebpageReallyLoaded' method after 200ms
// if additional frame or content is downloads in the meantime, this timer will be destroyed
// and the process repeated
m_pageHasntChangedTimer = new Timer();
EventHandler checker = delegate( object o1, EventArgs e1 ) {
// only if the page has been stable for 200ms already
// check the official browser state flag, (euphemistically called) 'Ready'
// and call our 'OnWebpageReallyLoaded' method
if ( WebBrowserReadyState.Complete == webBrowser.ReadyState ) {
m_pageHasntChangedTimer.Dispose();
OnWebpageReallyLoaded();
}
};
m_pageHasntChangedTimer.Tick += checker;
m_pageHasntChangedTimer.Interval = 200;
m_pageHasntChangedTimer.Start();
}
OnWebpageReallyLoaded() {
/* place your harvester code here */
}