2017-02-14 172 views
1

我試圖在下面的代碼中看到Google的reclocha在Clojurescript/Reagent SPA中。爲什麼我不能將Clojurescript函數作爲回調函數傳遞給Javascript?

(ns myapp.captcha 
    (:require [reagent.core :as r] 
      [cljs.core.async :refer [<! >! chan]]) 
    (:require-macros [cljs.core.async.macros :refer [go go-loop]])) 

(def captcha-ch (chan)) 

(defn ^:export data-callback [human-proof] 
    (go (>! captcha-ch {:captcha-data human-proof}))) 

(defn ^:export data-expired-callback [] 
    (go (>! captcha-ch {:captcha-expired true}))) 

(defn captcha [site-key] 
    (let [grecaptcha-script (doto (.createElement js/document "script") 
          (.setAttribute "id" "grecaptcha-script") 
          (.setAttribute "src" "https://www.google.com/recaptcha/api.js")) 
     out-ch (chan) 
     comp (r/create-class 
       {:component-did-mount (fn [this] 
             (.appendChild (.-body js/document) 
                grecaptcha-script)) 
       :component-will-unmount (fn [this] 
             (.removeChild (.-body js/document) 
                 (.getElementById js/document "grecaptcha-script")) 
             (go (>! captcha-ch {:exit true}))) 
       :reagent-render (fn [this] 
           [:div.g-recaptcha 
            {:data-sitekey site-key 
            :data-callback "myapp.captcha.data_callback" 
            :data-expired-callback "myapp.captcha.data_expired_callback"}])})] 
    (go-loop [] 
     (let [msg (<! captcha-ch)] 
     (if-not (:exit msg) 
      (>! out-ch msg) 
      (recur)))) 

    {:chan out-ch :comp comp})) 

當驗證碼解決和數據的回調應該叫我得到一個錯誤說:

版ReCAPTCHA找不到用戶提供的功能: myapp.captcha.data_callback

另一方面,如果我從瀏覽器的調試器控制檯調用myapp.captcha.data_callback函數是可見的並且正確執行。 PS:現在請忽略全球陳,這是一個不同的問題。爲了解決這個問題,我必須明確地調用captcha進行渲染,這使我處於一些顯然與腳本加載順序相關的競爭條件。我承認這可能是一種更清潔的方法,但現在看到問題出在這裏很有趣。

+0

您是否試過「myapp.captcha.data-callback」而不是下劃線版本?你是否試圖用你的命名空間只是「回調」,即沒有任何命名空間問題,這可能是問題的原因? –

+0

對不起,我忘了回答你的問題。是。我嘗試使用&沒有命名空間,但它表現相同。 – vidi

回答

1

我有一個解決方法,但它有點破解。

我在recaptcha腳本之前添加了一個腳本元素。在這個腳本元素中,我定義了將調用轉發給我的clojurescript函數的回調函數。

請參閱下面的代碼。

仍然很好理解爲什麼我不能直接使用我的Clojurescript回調。

(defn captcha [handler] 
    (let [callback-hooks (let [s (.createElement js/document "script")] 
         (.setAttribute s "id" "captcha-callbacks") 
         (set! (.-text s) 
           (str "var captcha_data_callback = function(x) { myapp.captcha.data_callback(x)};" 
            "var captcha_data_expired_callback = function() { myapp.captcha.data_expired_callback()};")) 
         s) 
     grecaptcha-script (doto (.createElement js/document "script") 
          (.setAttribute "id" "grecaptcha-script") 
          (.setAttribute "src" "https://www.google.com/recaptcha/api.js")) 
     captcha-div [:div.g-recaptcha 
        {:data-sitekey config/grecaptcha-client-key 
         :data-callback "captcha_data_callback" 
         :data-expired-callback "captcha_data_expired_callback"}]] 

    (go-loop [] 
     (let [msg (<! captcha-ch)] 
     (handler msg) 

     (if-not (:end msg) 
      (recur)))) 

    (r/create-class 
    {:component-did-mount (fn [this] 
          (doto (.-body js/document) 
           (.appendChild callback-hooks) 
           (.appendChild grecaptcha-script))) 
     :component-will-unmount (fn [this] 
           (doto (.-body js/document) 
            (.removeChild (.getElementById js/document "captcha-callbacks")) 
            (.removeChild (.getElementById js/document "grecaptcha-script"))) 
           (go (>! captcha-ch {:end true}))) 
     :reagent-render (fn [this] captcha-div)}))) 
相關問題