2

因此,我开始使用 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: Cannot read property 'readyState' of null [line #6277]

错误出现在自动生成的代码中,似乎与我专门编写的内容无关。如果我从我的代码中取出所有对 ReadyState 的引用,我仍然会收到错误消息。

我错过了什么?我觉得它与 Lambda 函数有关。

4

1 回答 1

1

您的问题是您希望whttp.Send阻止。Send,作为它的 JavaScript 等价物,是异步的。在POST甚至可以执行之前,whttp对象被释放(在finally块中)。当回调 ( OnReadyStateChanged) 被调用时,whttp它已经被释放(并且现在是空的),然后你试图调用ReadyState那个被释放的(空)对象。

造成混淆的另一个原因是,object.Free在 Windows/OS X 的 Delphi 中销毁对象,而在 Smart 中,它仅设置对 JavaScript 的垃圾收集的object引用nil并将销毁留给 JavaScript 的垃圾收集。这就是为什么在 thewhttp之后仍然存在Free以及为什么OnReadyStateChanged根本调用 the 的原因。

这工作正常:

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;
于 2014-02-08T15:22:14.097 回答