4

我正在尝试drakma-async在我的小项目中使用。但我就是不明白发生了什么。(我使用 emacs + slime + ccl)。我需要使用 http(s) 获取数据并在回调中解析它。我假设我可以得到无法解析的错误数据,所以我想重试。但是当我尝试进行一些测试时,我就是无法理解发生了什么......

(defun my-callback (data)
  (prin1 data)
  (restart-case
      (error "Some error parsing data...")
    (just-continue () (prin1 "Continue..."))))

(defun simple-test ()
  (let ((future (asf:make-future)))
    (as:delay #'(lambda () (asf:finish future "Some data")) :time 2)
    (prin1 (asf:future-finished-p future))
    (asf:attach future #'my-callback)))

(defun drakma-test ()
  (asf:alet ((response (das:http-request "http://www.google.com")))
    ;(prin1 (asf:future-finished-p response))
    (asf:attach response #'my-callback)))

(defun drakma-test-let ()
  (let ((response (das:http-request "http://www.google.com")))
    ;(prin1 (asf:future-finished-p response))
    (asf:attach response #'my-callback)))

(defun run-test (test)
  (as:start-event-loop test))

1)所以我将这就是我的简单示例(这就是我计划的)

? (run-test #'simple-test)
NIL"Some data"    ;I get debugger here with simple-error and choose my restart
Invoking restart: #<RESTART JUST-CONTINUE #x7F0578EC20AD>
"Continue..."
1

2)这是我在第二次测试中得到的:

? (run-test #'drakma-test)
"<A LOT OF HTML>
"
1

我的调试器和重启在哪里?

3)取消注释中的;(prin1 (asf:future...))drakma-test

? (run-test #'drakma-test)
1

没有完成/未完成的布尔,没有数据没有打印,我没有重新启动,我只是得到1结果。

4)我假设如果我写(let ((reponse (das:http-request "http://www.google.com"))) ... ) instad(asf:alet ...)response不包含future对象,但会阻塞直到请求完成并且response将包含数据。

? (run-test #'drakma-test-let)
1

5)取消注释中的;(prin1 (asf:future...))drakma-test-let

? (run-test #'drakma-test-let)
NIL   ;future is not finished
1

没有打印数据,只是没有完成和运行测试的结果。

我已经为 cl-async 运行了测试,除了 ipv6 测试之外,它们都通过了。所以我只是不知道从哪里开始了解发生了什么......为什么我没有调试器并在第二次测试中重新启动?为什么在第三次测试中没有任何反应(它与第二次相同,但使用 prin1)。为什么第 5 次和第 5 次测试没有任何反应?

PS 没有足够的声誉来创建drakma-asynccl-async标记此库。我知道这drakma-async是建立的,drakma所以我放了这个标签。

4

1 回答 1

1

感谢 mn 的评论,使情况更加清晰,并简要说明了情况。

我做了一些例子,并想展示每种情况下会发生什么:

例子:

(defun my-callback (&rest data)
  (format t "Echo from callback: ~A~%" data)
  (restart-case
      (error "Some error parsing data...")
    (just-continue () (prin1 "Continue..."))))

(defun my-errback (e)
  (format t "Echo from errback: ~A~%" e))

(defun make-example-future ()
  (let ((future (asf:make-future))) ;creating future
    (as:delay #'(lambda ()          ;finishing future in 2 seconds
                  (asf:future-handler-case ;wrapping asf:finish
                    (asf:finish future
                                "Result data")
                    (t (e) (asf:signal-error future e)))) ;signal future an error
              :time 2)
    future))

(defun simple-test-2 ()
  (let ((future (make-example-future)))
    (format t "Is future?: ~A~%Finished?: ~A~%"  
            (asf:futurep future) (asf:future-finished-p future))
    (asf:alet ((result future))
      (asf:attach-errback future #'my-errback)
      (format t "Finished? ~A~%" (asf:future-finished-p future))
      (asf:future-finished-p result)
      (asf:attach result #'my-callback))))

这就是正在发生的事情:

? (as:start-event-loop #'simple-test-2)
Is future?: T 
Finished?: NIL
;<here we have a 2 sec pause>
Finished? T
Echo from errback: There is no applicable method for the generic function:
#<STANDARD-GENERIC-FUNCTION CL-ASYNC-FUTURE:FUTURE-FINISHED-P #x302001B67A8F>
when called with arguments:
("Result data")

A)asf:alet等待结果并将结果值绑定到变量。所以我认为asf:alet绑定未来是错误的。

B)在make-example-future我们包装asf:finishasf:future-handler-case 使用asf:signal-error将错误发送到未来。这意味着错误被处理并且errback将被调用。即使稍后在代码中附加了回调。此外,错误(asf:future-finished-p result) 被处理了,future-handler-case因为它被包裹了asf:alet(至少我是这么认为的)。

C)评论(asf:future-finished-p result),结果是

Is future?: T
Finished?: NIL
Finished? T
Echo from callback: (Result data) ;here is my data
Echo from errback: Some error parsing data... ;;here is my error
1

里面有drakma-async类似future-handler-case的包装器asf:finish

所以这解释了#2测试结果。我得到了数据并asf:alet返回了字符串。来自回调的错误被传递给errback,我没有。而且。仅drakma-test使用asf:alet时我无法附加errback,因为我无法访问未来。我需要打电话http-requestlet而不是alet

这也解释了#3测试的结果:我收到了(future-finished-p)发送到的错误errback

如果我们查看结果#4#5使用 new 进行测试my-callback:可以看出, cl-async尝试使用drakma返回的所有值调用我的回调。其中有 7 个(drakma:http-request返回的值)。因此,我尝试附加错误数量的参数回调,而我的 #4 和 #5 测试发出一个错误信号,该错误只是由它处理future-hander-case并将其发送到errback.

drakma-async结果:无论如何,如果不删除它似乎不可能使用重新启动,future-handler-case因为它会向 errback 发送错误,但会丢失所有重新启动。

如果有人回答我的问题,希望这篇文章能有所帮助。

于 2014-09-29T12:23:02.787 回答