1

Clojurescript 中是否有办法创建异步函数或宏将函数包装到 Promise 中以模拟它?我当前的用例是用异步版本替换以下接受回调的函数 - 顺便说一句,这是针对AWS lambda 函数的。

// Old style
function(args, callback) {
  // Use callback(e) for errors
  // Use callback(null, value) for the result
}

// New style
async function(args) {
  return value; // success path
  throw new Error(); // error path
}

鉴于这是 Clojurescript,使用await不是问题。而且我知道这可以简单地返回一个 Promise 以符合async要求。因此它解析为一些糖代码来创建 Promise,为我捕获所有错误并在快乐的路径上调用 resolve 或以其他方式拒绝。

浏览clojure.core.async和文档 - 包括clojurescript 参考,我没有找到任何东西。

4

1 回答 1

1

Node 8 和更新版本附带util.promisify 可以满足您的要求:

采用遵循常见错误优先回调风格的函数,即采用 (err, value) => ... 回调作为最后一个参数,并返回一个返回承诺的版本。

编辑:我花了一点时间写了一个宏,promisify我对结果很满意。请注意,宏需要保存在 CLJC 文件中:

;; macros.cljc ;;;;;;;;;;
(ns server.macros)

(defmacro promisify [method obj params]
  `(js/Promise.
    (fn [resolve# reject#]
      (~method ~obj ~params
       (fn [err# result#]
         (if err#
           (reject# err#)
           (resolve# result#)))))))

;; main.cljs ;;;;;;;;;;
(ns server.main
  (:require-macros [server.macros :refer [promisify]])
  (:require ["aws-sdk" :as aws]))

(defn main! []
  (println "App loaded...")
  (let [creds (aws/SharedIniFileCredentials. #js {:profile "example-profile"})
        _     (set! (.-credentials aws/config) creds)
        s3    (aws/S3.)]
    (-> (promisify .listBuckets s3 #js {})
        (.then #(println "DATA:" %))
        (.catch #(println "ERROR:" %)))))

并且输出与以前相同:

$ node target/main.js

App loaded...
DATA: #js {:Buckets #js [#js {:Name demo-test-bucket, :CreationDate #inst "2019-05-05T17:32:17.000-00:00"} #js {:Name subdomain.mydomain.com, :CreationDate #inst "2019-06-19T04:16:10.000-00:00"}], :Owner #js {:DisplayName username, :ID 9f7947b2d509e2338357d93e74f2f88a7528319ab3609b8d3b5be6b3a872dd2c}}

该宏基本上是这段代码的 Clojure 版本。

编辑 2 :如果您也真的想使用 core.async,还有这个库可能会很有趣。

于 2020-05-04T04:42:36.503 回答