Как отправить данные POST с помощью TW3HttpRequest
Поэтому я начал играть с помощью SMS и попытался создать программу (ярлык и кнопку), чтобы попасть на веб-сайт с запросом на публикацию и отобразить результат.
У меня нет проблем с подсказками / предупреждениями / ошибками, и все выглядит хорошо для меня. Следующий код представляет собой переделку пары существующих примеров, соединенных вместе.
procedure TForm1.ExecuteCmd;
var
whttp : TW3HttpRequest;
wParams : string;
begin
wHttp := TW3HttpRequest.Create;
try
whttp.OnDataReady := lambda (Sender)
if (w3Label1.caption = '') then
w3Label1.caption := wHttp.ResponseText;
end;
whttp.OnReadyStateChange := lambda (Sender)
if (wHttp.ReadyState = 4) and (wHttp.Status = 200) then
begin
if (w3Label1.caption = '') then
w3Label1.caption := wHttp.ResponseText;
end;
end;
wParams := 'cmd=TestID1';
whttp.open('POST','http://www.server1.com/executecmd.php');
whttp.RequestHeaders['Content-type'] := 'application/x-www-form-urlencoded';
whttp.Send(wParams);
finally
wHttp.free;
end;
end;
procedure TForm1.W3Button1Click(Sender: TObject);
begin
ExecuteCmd;
end;
Проблема в том, что когда я фактически нажимаю кнопку, я получаю следующее сообщение об ошибке: Uncaught TypeError: Невозможно прочитать свойство 'readyState' из null [строка #6277]
Ошибка в автоматически сгенерированном коде и, похоже, не имеет отношения к тому, что я написал специально. Если я уберу все ссылки на ReadyState из своего кода, я все равно получу ошибку.
Что мне не хватает? Я чувствую, что это как-то связано с лямбда-функциями.
1 ответ
Ваша проблема в том, что вы ожидаете whttp.Send
блокировать. Send
, как его эквивалент JavaScript, является асинхронным. Перед POST
может даже выполнить, whttp
объект освобожден (в finally
блок). Когда обратный звонок (OnReadyStateChanged
) называется, whttp
был уже освобожден (и теперь является нулевым), а затем вы пытаетесь позвонить ReadyState
на этом освобожденном (нулевом) объекте.
Еще одна причина путаницы в том, что object.Free
в Delphi для Windows/OS X уничтожает объект, в то время как в Smart он просто устанавливает object
ссылка на nil
и оставляет уничтожение для сборки мусора JavaScript. Вот почему whttp
все еще жив после Free
и почему OnReadyStateChanged
называется вообще.
Это отлично работает:
uses
W3System, W3Graphics, W3Components, W3Forms, W3Fonts, W3Borders, W3Application,
W3Button, W3Inet, W3Memo;
type
TForm1=class(TW3form)
procedure W3Button1Click(Sender: TObject);
private
{$I 'Form1:intf'}
whttp: TW3HttpRequest;
protected
procedure InitializeForm; override;
procedure InitializeObject; override;
procedure Resize; override;
end;
implementation
{ TForm1}
procedure TForm1.W3Button1Click(Sender: TObject);
var
wParams: string;
begin
whttp := TW3HttpRequest.Create;
whttp.OnReadyStateChange := lambda (Sender)
if (whttp.ReadyState = 4) and (wHttp.Status = 200) then
begin
W3Memo1.Text := wHttp.ResponseText;
whttp.OnReadyStateChange := nil;
whttp := nil;
end;
end;
wParams := 'cmd=TestID1';
whttp.open('POST','http://httpbin.org/post');
whttp.RequestHeaders['Content-type'] := 'application/x-www-form-urlencoded';
whttp.Send(wParams);
end;