【问题标题】:Clojurescript - Recur from anonymous function promise callbackClojurescript - 从匿名函数承诺回调中重现
【发布时间】:2018-12-03 23:44:26
【问题描述】:

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

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

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

"name1": [val1,val2,val3]

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

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

为此,我想出了以下sn-p:

(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})))))))

不幸的是,这不起作用,因为它不是 recur 进入循环,而是返回到 (fn)。然而,这个 (fn) 回调是必需的,因为 (.getItem) 调用返回一个我无法访问的承诺。

我的问题是,有没有办法让这个 promise 值出来并重新循环到循环中,或者有更好的方法来做到这一点?

【问题讨论】:

  • 使用 Promise.all 不是更好更地道(就 cljs 和 js 而言)?类似:(.then (Promise/all (map #(.then (.getItem localforage %) (fn [v] [% v])) project-map)) (partial into {}))

标签: javascript recursion clojure promise clojurescript


【解决方案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 是否安全。

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 2017-04-26
    • 2020-08-26
    • 2019-04-15
    • 2017-04-05
    • 2015-08-13
    相关资源
    最近更新 更多