[Fix #1785] Handle timeout for network failure in utils.utils/http-get and http-post

Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
Foo Pang 2018-01-09 10:36:48 +08:00 committed by Julien Eluard
parent 1b5b6e33b4
commit 27e777d1bd
No known key found for this signature in database
GPG Key ID: 6FD7DB5437FCBEF6
11 changed files with 70 additions and 31 deletions

View File

@ -48,7 +48,8 @@
"rn-snoopy/stream/filter", "rn-snoopy/stream/filter",
"rn-snoopy/stream/buffer", "rn-snoopy/stream/buffer",
"react-native/Libraries/vendor/emitter/EventEmitter", "react-native/Libraries/vendor/emitter/EventEmitter",
"react-native-background-timer" "react-native-background-timer",
"react-native-fetch-polyfill"
], ],
"imageDirs": [ "imageDirs": [
"resources/images" "resources/images"

5
package-lock.json generated
View File

@ -8088,6 +8088,11 @@
"resolved": "https://registry.npmjs.org/react-native-fcm/-/react-native-fcm-10.0.3.tgz", "resolved": "https://registry.npmjs.org/react-native-fcm/-/react-native-fcm-10.0.3.tgz",
"integrity": "sha1-HcU47YifkLelvB0FMMxRbmmwnow=" "integrity": "sha1-HcU47YifkLelvB0FMMxRbmmwnow="
}, },
"react-native-fetch-polyfill": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/react-native-fetch-polyfill/-/react-native-fetch-polyfill-1.1.2.tgz",
"integrity": "sha1-JWtaCr14zEmS96fPglQ9ovISSnM="
},
"react-native-fs": { "react-native-fs": {
"version": "2.8.1", "version": "2.8.1",
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.8.1.tgz", "resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.8.1.tgz",

View File

@ -53,6 +53,7 @@
"react-native-crypto": "2.1.1", "react-native-crypto": "2.1.1",
"react-native-dialogs": "0.0.20", "react-native-dialogs": "0.0.20",
"react-native-fcm": "10.0.3", "react-native-fcm": "10.0.3",
"react-native-fetch-polyfill": "1.1.2",
"react-native-fs": "2.8.1", "react-native-fs": "2.8.1",
"react-native-http": "github:tradle/react-native-http#834492d", "react-native-http": "github:tradle/react-native-http#834492d",
"react-native-http-bridge": "github:status-im/react-native-http-bridge", "react-native-http-bridge": "github:status-im/react-native-http-bridge",

View File

@ -30,3 +30,4 @@
(def snoopy-buffer (js/require "rn-snoopy/stream/buffer")) (def snoopy-buffer (js/require "rn-snoopy/stream/buffer"))
(def EventEmmiter (js/require "react-native/Libraries/vendor/emitter/EventEmitter")) (def EventEmmiter (js/require "react-native/Libraries/vendor/emitter/EventEmitter"))
(def background-timer (.-default (js/require "react-native-background-timer"))) (def background-timer (.-default (js/require "react-native-background-timer")))
(def fetch (.-default (js/require "react-native-fetch-polyfill")))

View File

@ -109,21 +109,18 @@
(re-frame/reg-fx (re-frame/reg-fx
:http-post :http-post
(fn [{:keys [action data success-event-creator failure-event-creator]}] (fn [{:keys [action data success-event-creator failure-event-creator timeout-ms]}]
(utils/http-post action (let [on-success #(re-frame/dispatch (success-event-creator %))
data on-error #(re-frame/dispatch (failure-event-creator %))
#(re-frame/dispatch (success-event-creator %)) opts {:timeout-ms timeout-ms}]
#(re-frame/dispatch (failure-event-creator %))))) (utils/http-post action data on-success on-error opts))))
(defn- http-get [{:keys [url response-validator success-event-creator failure-event-creator]}] (defn- http-get [{:keys [url response-validator success-event-creator failure-event-creator timeout-ms]}]
(if response-validator (let [on-success #(re-frame/dispatch (success-event-creator %))
(utils/http-get url on-error #(re-frame/dispatch (failure-event-creator %))
response-validator opts {:valid-response? response-validator
#(re-frame/dispatch (success-event-creator %)) :timeout-ms timeout-ms}]
#(re-frame/dispatch (failure-event-creator %))) (utils/http-get url on-success on-error opts)))
(utils/http-get url
#(re-frame/dispatch (success-event-creator %))
#(re-frame/dispatch (failure-event-creator %)))))
(re-frame/reg-fx (re-frame/reg-fx
:http-get :http-get

View File

@ -119,7 +119,7 @@
:success-event :update-transactions-success :success-event :update-transactions-success
:error-event :update-transactions-fail} :error-event :update-transactions-fail}
:db (-> db :db (-> db
(clear-error-message :transaction-update) (clear-error-message :transactions-update)
(assoc-in [:wallet :transactions-loading?] true))}))) (assoc-in [:wallet :transactions-loading?] true))})))
(handlers/register-handler-db (handlers/register-handler-db
@ -219,3 +219,8 @@
:wallet/update-gas-price-success :wallet/update-gas-price-success
(fn [db [_ price edit?]] (fn [db [_ price edit?]]
(assoc-in db [:wallet (if edit? :edit :send-transaction) :gas-price] price))) (assoc-in db [:wallet (if edit? :edit :send-transaction) :gas-price] price)))
(handlers/register-handler-fx
:wallet/show-error
(fn []
{:show-error (i18n/label :t/wallet-error)}))

View File

@ -38,3 +38,9 @@
:<- [:wallet] :<- [:wallet]
(fn [wallet] (fn [wallet]
(:balance-loading? wallet))) (:balance-loading? wallet)))
(reg-sub :wallet/error-message?
:<- [:wallet]
(fn [wallet]
(or (get-in wallet [:errors :balance-update])
(get-in wallet [:errors :prices-update]))))

View File

@ -159,3 +159,8 @@
(reg-sub :wallet.transactions/filters (reg-sub :wallet.transactions/filters
(fn [db] (fn [db]
(get-in db [:wallet.transactions :filters]))) (get-in db [:wallet.transactions :filters])))
(reg-sub :wallet.transactions/error-message?
:<- [:wallet]
(fn [wallet]
(get-in wallet [:errors :transactions-update])))

View File

@ -102,8 +102,11 @@
(defview history-list [] (defview history-list []
(letsubs [transactions-history-list [:wallet.transactions/transactions-history-list] (letsubs [transactions-history-list [:wallet.transactions/transactions-history-list]
transactions-loading? [:wallet.transactions/transactions-loading?] transactions-loading? [:wallet.transactions/transactions-loading?]
error-message? [:wallet.transactions/error-message?]
filter-data [:wallet.transactions/filters]] filter-data [:wallet.transactions/filters]]
[react/view components.styles/flex [react/view components.styles/flex
(when error-message?
(re-frame/dispatch [:wallet/show-error]))
[list/section-list {:sections (map #(update-transactions % filter-data) transactions-history-list) [list/section-list {:sections (map #(update-transactions % filter-data) transactions-history-list)
:render-fn render-transaction :render-fn render-transaction
:empty-component [react/text {:style styles/empty-text} :empty-component [react/text {:style styles/empty-text}

View File

@ -58,7 +58,7 @@
(defn current-tokens [visible-tokens network] (defn current-tokens [visible-tokens network]
(filter #(contains? visible-tokens (:symbol %)) (tokens/tokens-for (ethereum/network->chain-keyword network)))) (filter #(contains? visible-tokens (:symbol %)) (tokens/tokens-for (ethereum/network->chain-keyword network))))
(defn- asset-section [network balance visible-tokens prices-loading? balance-loading?] (defn- asset-section [network balance visible-tokens refreshing?]
(let [tokens (current-tokens visible-tokens network) (let [tokens (current-tokens visible-tokens network)
assets (map #(assoc % :amount (get balance (:symbol %))) (concat [tokens/ethereum] tokens))] assets (map #(assoc % :amount (get balance (:symbol %))) (concat [tokens/ethereum] tokens))]
[react/view styles/asset-section [react/view styles/asset-section
@ -68,7 +68,7 @@
:data assets :data assets
:render-fn render-asset :render-fn render-asset
:on-refresh #(re-frame/dispatch [:update-wallet (map :symbol tokens)]) :on-refresh #(re-frame/dispatch [:update-wallet (map :symbol tokens)])
:refreshing (boolean (or prices-loading? balance-loading?))}]])) :refreshing refreshing?}]]))
(defview wallet [] (defview wallet []
(letsubs [network [:network] (letsubs [network [:network]
@ -76,11 +76,16 @@
visible-tokens [:wallet.settings/visible-tokens] visible-tokens [:wallet.settings/visible-tokens]
portfolio-value [:portfolio-value] portfolio-value [:portfolio-value]
prices-loading? [:prices-loading?] prices-loading? [:prices-loading?]
balance-loading? [:wallet/balance-loading?]] balance-loading? [:wallet/balance-loading?]
error-message? [:wallet/error-message?]]
[react/view {:style components.styles/flex} [react/view {:style components.styles/flex}
(when error-message?
(re-frame/dispatch [:wallet/show-error]))
[toolbar-view] [toolbar-view]
[react/view components.styles/flex [react/view components.styles/flex
[total-section portfolio-value] [total-section portfolio-value]
[list/action-list actions [list/action-list actions
{:container-style styles/action-section}] {:container-style styles/action-section}]
[asset-section network balance visible-tokens prices-loading? balance-loading?]]])) [asset-section network balance visible-tokens
(and (or prices-loading? balance-loading?)
(not error-message?))]]]))

View File

@ -1,8 +1,12 @@
(ns status-im.utils.utils (ns status-im.utils.utils
(:require [status-im.constants :as const] (:require [status-im.constants :as const]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[clojure.string :as str]
[status-im.react-native.js-dependencies :as rn-dependencies])) [status-im.react-native.js-dependencies :as rn-dependencies]))
;; Default HTTP request timeout ms
(def http-request-default-timeout-ms 3000)
(defn show-popup [title content] (defn show-popup [title content]
(.alert (.-Alert rn-dependencies/react-native) (.alert (.-Alert rn-dependencies/react-native)
title title
@ -38,31 +42,37 @@
{:text (i18n/label :t/yes) :onPress on-accept}))))) {:text (i18n/label :t/yes) :onPress on-accept})))))
(defn http-post (defn http-post
"Performs an HTTP POST request"
([action data on-success] ([action data on-success]
(http-post action data on-success nil)) (http-post action data on-success nil))
([action data on-success on-error] ([action data on-success on-error]
(-> (.fetch js/window (http-post action data on-success on-error nil))
(str const/server-address action) ([action data on-success on-error {:keys [timeout-ms] :as opts}]
(clj->js {:method "POST" (-> (rn-dependencies/fetch (str const/server-address action)
:headers {:accept "application/json" (clj->js {:method "POST"
:content-type "application/json"} :headers {:accept "application/json"
:body (.stringify js/JSON (clj->js data))})) :content-type "application/json"}
:body (.stringify js/JSON (clj->js data))
:timeout (or timeout-ms http-request-default-timeout-ms)}))
(.then (fn [response] (.then (fn [response]
(.text response))) (.text response)))
(.then (fn [text] (.then (fn [text]
(let [json (.parse js/JSON text) (let [json (.parse js/JSON text)
obj (js->clj json :keywordize-keys true)] obj (js->clj json :keywordize-keys true)]
(on-success obj)))) (on-success obj))))
(.catch (or on-error (.catch (or on-error
(fn [error] (fn [error]
(show-popup "Error" (str error)))))))) (show-popup "Error" (str error))))))))
(defn http-get (defn http-get
"Performs an HTTP GET request"
([url on-success on-error] ([url on-success on-error]
(http-get url nil on-success on-error)) (http-get url on-success on-error nil))
([url valid-response? on-success on-error] ([url on-success on-error {:keys [valid-response? timeout-ms] :as opts}]
(-> (.fetch js/window url (clj->js {:method "GET" (-> (rn-dependencies/fetch url
:headers {"Cache-Control" "no-cache"}})) (clj->js {:method "GET"
:headers {"Cache-Control" "no-cache"}
:timeout (or timeout-ms http-request-default-timeout-ms)}))
(.then (fn [response] (.then (fn [response]
(let [ok? (.-ok response) (let [ok? (.-ok response)
ok?' (if valid-response? ok?' (if valid-response?