我试图在我的小项目中使用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"))) ... )
(asf:alet ...)
的{{1}}的instad将不包含response
个对象,但会阻止,直到请求完成并且future
将包含数据。
response
5)取消注释? (run-test #'drakma-test-let)
1
;(prin1 (asf:future...))
行
drakma-test-let
不打印数据,只是未完成数据和运行测试的结果。
我已经运行了cl-async的测试,除了ipv6测试之外,它们都通过了。所以我只是不知道从哪里开始了解发生了什么...为什么我没有调试器并重新启动第二次测试?为什么在第3次测试中没有任何反应(它与第2次测试相同,但使用prin1)。为什么第5和第5次测试没有任何反应?
P.S。没有足够的声誉为此库创建? (run-test #'drakma-test-let)
NIL ;future is not finished
1
或drakma-async
标记。我知道cl-async
建立在drakma-async
之上,所以我把这个标记。
答案 0 :(得分:1)
感谢m-n的评论,使情况更加清晰,并简要解释了情况。
我做了一些例子,想要展示每种情况下会发生什么:
示例:
(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:finish
打包asf: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
的{{1}}中,我无法附加asf:alet
,因为我无法访问未来。我需要在errback
中致电http-request
,而不是let
。
这也解释了alet
测试的结果:#3
中的错误已发送到(future-finished-p)
。
如果我们使用新errback
查看#4
和#5
测试的结果:可以看出,
my-callback
尝试使用cl-async
返回的所有值调用我的回调。其中有7个(drakma
返回的值)。
所以我试图附加错误数量的参数回调,我的#4和#5测试发出错误信号,只是由drakma:http-request
处理并将其发送到future-hander-case
。
结果:
无论如何,似乎不可能在不删除errback
的情况下使用drakma-async
重新启动,因为它会向errback发送错误,但会丢失所有重新启动。
希望如果有人填写我的问题,这篇文章会有所帮助。