xuchunyang/youdao-dictionary.el

请教关于有道词典异步获取的问题

EvanMeek opened this issue · 12 comments

作者您好,我正在使用您开发的有道词典插件,功能非常好用。我现在有一个个人计划,现有一个生词表,通过org-capture捕获光标下的单词,并且通过您的youdao-dictionary进行翻译,将一些有用的信息插入到生词表中(例如english,词性,中文)。目前我已经可以正确获取我所需要的信息,但是在使用org-capture是出现了问题,问题如下:

captureError

我猜测可能是因为youdao-dictionary是异步请求的,所以在capture获取时没有立即获取到就返回了错误的信息。

下面是我的capture模板

capture-template

下面是我获取对应信息的函数

capture-function

由于我个人水平有限,请教下您如何在capture时做一个小延迟,让youdao-dictionary有返回值后再获取捕获的结果

(youdao-dictionary--request WORD &optional CALLBACK) 在没提供 CALLBACK 时是同步的,不是异步的:

(youdao-dictionary--request "hello")
;; => ((translation . ["你好"]) (basic (us-phonetic . "helˈō") (phonetic . "həˈləʊ") (uk-phonetic . "həˈləʊ") (explains . ["int. 喂;哈罗,你好,您好" "n. 表示问候, 惊奇或唤起注意时的用语" "n. (Hello) 人名;(法)埃洛"])) (query . "hello") (errorCode . 0) (web . [(... ...) (... ...) (... ...)]))

你得到了 json-unknown-keyword 错误,说明有道服务器返回数据不是合法 json,你查了哪个词能重现这个问题?

;; no 不是合法的 json
(json-read-from-string "no")
;; error-> (json-unknown-keyword "no")

P.S. 你可以用 Markdown 语法贴代码,编辑器右上角有个 <> Insert Code 的按钮。你的代码没贴全,函数结尾看不到。

P.S. 你可以用 Markdown 语法贴代码,编辑器右上角有个 <> Insert Code 的按钮。你的代码没贴全,函数结尾看不到。

多谢提醒,下面是函数的定义:

(defun evan/capture-get-word-eng(type)
	(interactive "^p")
	(let* ((point-word (thing-at-point 'word))
		   (evan/capture-word-translate (youdao-dictionary--request point-word))
		   (evan/capture-word-eng point-word)
		   (evan/capture-word-chinese (cdar (nthcdr 3 (cdadr evan/capture-word-translate))))
		   (evan/capture-word-type nil))
	  ;; 获取单词词性
	  (progn (string-match "[a-zA-Z]+" (aref evan/capture-word-chinese 0)) ;; 匹配英文字符
			 ;; 设置词性 格式为: "adj."
			 (setq evan/capture-word-type (concat (match-string 0 (aref evan/capture-word-chinese 0)) ".")))
	  
	  ;; 设置单词中文
	  (progn (string-match "[\u4e00-\u9fa5;,]+" (aref evan/capture-word-chinese 0))
			 ;; 设置中文
			 (setq evan/capture-word-chinese (match-string 0 (aref evan/capture-word-chinese 0))))
	  ;; 根据参数返回具体的值
	  (cond ((eq type 1) evan/capture-word-eng)
			((eq type 2) evan/capture-word-type)
			((eq type 3) evan/capture-word-chinese))))

我不知道怎么回事,你得到的 json-unknown-error 是哪里来的?你能不能找找具体什么地方出了问题。

(youdao-dictionary--request WORD &optional CALLBACK) 在没提供 CALLBACK 时是同步的,不是异步的:

(youdao-dictionary--request "hello")
;; => ((translation . ["你好"]) (basic (us-phonetic . "helˈō") (phonetic . "həˈləʊ") (uk-phonetic . "həˈləʊ") (explains . ["int. 喂;哈罗,你好,您好" "n. 表示问候, 惊奇或唤起注意时的用语" "n. (Hello) 人名;(法)埃洛"])) (query . "hello") (errorCode . 0) (web . [(... ...) (... ...) (... ...)]))

你得到了 json-unknown-keyword 错误,说明有道服务器返回数据不是合法 json,你查了哪个词能重现这个问题?

;; no 不是合法的 json
(json-read-from-string "no")
;; error-> (json-unknown-keyword "no")

前面我用的是老版本的youdao-dictionary,现在已经更新了,能看到callback参数了。

不过仍然会有json-unknow-error问题(单独调用youdao-dictionary--request是没问题的),是不是因为capture模板那边调用我的函数时就立即返回了,没有等待数据。。。

刚刚又测试了一下,我发现好像是因为光标下没有单词所以point-word永远为nil,因为我是先呼出capture,然后再通过capture的模板调用函数的,所以光标下的单词永远为空..

噢,原来如此,缺少参数时候返回的不是 json:

$ curl 'http://fanyi.youdao.com/openapi.do?keyfrom=YouDaoCV&key=659600698&type=data&doctype=json&version=1.1&q='
no query

因为 youdao-dictionary--request 没检查参数,你需要自己检查。

而且这个 API 比较简单,你可以自己发送请求,这样就不用我这个包了,比如:

(defun your-youdao (word)
  (with-current-buffer
      (url-retrieve-synchronously
       (concat "http://fanyi.youdao.com/openapi.do?keyfrom=YouDaoCV&key=659600698&type=data&doctype=json&version=1.1&q="
               (url-hexify-string word)))
    (goto-char url-http-end-of-headers)
    (json-read)))

而且你的 Org Capture 模版同一个词发送了三次请求,应该避免,发送一次就够了。

而且你的 Org Capture 模版同一个词发送了三次请求,应该避免,发送一次就够了。

而且你的 Org Capture 模版同一个词发送了三次请求,应该避免,发送一次就够了。

不小心点错了,把issue关闭了。。

我想着youdao-dictionary不是有个缓存嘛,相同的单词会直接从缓存里拿。

噢,原来如此,缺少参数时候返回的不是 json:

$ curl 'http://fanyi.youdao.com/openapi.do?keyfrom=YouDaoCV&key=659600698&type=data&doctype=json&version=1.1&q='
no query

因为 youdao-dictionary--request 没检查参数,你需要自己检查。

而且这个 API 比较简单,你可以自己发送请求,这样就不用我这个包了,比如:

(defun your-youdao (word)
  (with-current-buffer
      (url-retrieve-synchronously
       (concat "http://fanyi.youdao.com/openapi.do?keyfrom=YouDaoCV&key=659600698&type=data&doctype=json&version=1.1&q="
               (url-hexify-string word)))
    (goto-char url-http-end-of-headers)
    (json-read)))

多谢

你的问题应该解决了,我关闭此 issue 了。