Clojurescript-从匿名函数的承诺回调中恢复

时间:2018-12-03 23:44:27

标签: javascript recursion clojure promise clojurescript

我正在使用clojurescript和localforage基于Promise的存储库。我在localstorage中设置了以下结构作为键值对

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

那么每个“名称”都是另一组值的键。

"name1": [val1,val2,val3]

我目前在这里有名称列表,现在需要遍历该列表,获取每个列表的值,然后返回格式如下的地图:

{: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)调用会返回一个我无法访问的承诺。

然后我的问题是,有没有办法使承诺值消失并重新循环,或者有更好的总体方法呢?

1 个答案:

答案 0 :(得分:1)

我不知道如何选择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是否安全。