Clojurescript - 从匿名函数承诺回调中重复出现

Clojurescript - Recur from anonymous function promise callback

我正在使用 clojurescript 和 localforage 基于 promise 的存储库。我在本地存储中设置了如下结构作为键值对

"names" : ["name1","name2","name3"]

然后每个 "names" 是另一组值的键。

"name1": [val1,val2,val3]

我目前正处于拥有名称列表的位置,现在需要遍历该列表,获取每个值,然后 return 格式如下的地图:

{:name1 [val1,val2,val3] :name2 [val1,val2]}

为此,我想出了以下代码片段:

(defn get-project-dates [project-map]
  "Handles getting all the times/dates for project"
  (loop [i 0
        project-dates {}]
    (if (= i (count project-map))
      project-dates
      (.then (.getItem localforage (nth project-map i)) (fn [promiseVal]
          (recur (inc i) (conj project-dates {(key (nth project-map i)) promiseVale})))))))

不幸的是,这不起作用,因为它不会重新进入循环,而是返回到 (fn)。然而,此 (fn) 回调是必需的,因为 (.getItem) 调用 return 是我无法以其他方式访问的承诺。

我的问题是,有没有一种方法可以将承诺值取出并重新出现在循环中,或者有更好的整体方法来做到这一点?

据我所知,无法选择您想 recur 加入的内容。据我所知,这完全取决于范围。

不过你可以让它成为一个直接的递归函数。您可以通过几种方式进行设置:

; Give it two argument lists. The 1-arity version is meant to be called by the user, 
;  while the 3-arity version is meant for recursive calls 
(defn get-project-dates
  ([project-map i project-dates]
   (if (= i (count project-map))
     project-dates
     (.then (.getItem localforage (nth project-map i))
            (fn [promiseVal]
              (get-project-dates
                project-map
                (inc i)
                (conj project-dates {(key (nth project-map i)) promiseVale}))))))

  ([project-map]
   (get-project-dates project-map 0 {})))

(defn get-project-dates [project-map]
  ; Define a local recursive function called "rec" (or whatever)
  (letfn [(rec [i project-dates]
            (if (= i (count project-map))
              project-dates
              (.then (.getItem localforage (nth project-map i))
                     (fn [promiseVal]
                       (rec
                         (inc i)
                         (conj project-dates {(key (nth project-map i)) promiseVale}))))))]

    ; Then start the recursion off
    (rec 0 {})))

第二个的好处是不需要不断传递 project-map,函数名也更简洁。

当然,如果你的递归调用量过大,你需要谨慎。您需要测试一下缺少 recur 是否安全。