Redux-observable POST ajax request 从不发送网络请求

Redux-observable POST ajax request never sends the network request

我有这个 redux-observable epic that POSTs a json body to my backend, but it never actually gets so far as to send the actual network request. It uses Rx.DOM.Request.post(url, [body])(我想?请查看我的导入以确认)。我可以验证网络请求永远不会从我的应用程序中发出,更不用说到达我的后端了:

import { Observable } from 'rxjs'
import 'redux-observable'
import {
  UPLOAD_IMAGE,
  UPLOAD_IMAGE_FULFILLED,
  UPLOAD_IMAGE_REJECTED,
  UPLOAD_PRODUCT,
  uploadImageFulfilled,
  uploadImageRejected,
  uploadProductFulfilled,
  uploadProductRejected
} from './addForm.action'
import {
  updateAlertModalIsOpen,
  updateAlertModalMessage,
  updateAlertModalTitle
} from '../alert-modal/alertModal.action'
import 'rxjs/add/operator/catch'
import { RNS3 } from 'react-native-aws3'
import { ajax } from 'rxjs/observable/dom/ajax'

export const uploadProductEpic = action$ =>
  action$.ofType(UPLOAD_PRODUCT)
    .mergeMap(action => {
      ajax.post(
        'http://192.168.20.3:4000/products', 
        action.payload,
        { 'Content-Type': 'application/json' })
    })
    .map(response => uploadProductFulfilled(response))
    .catch(error => Observable.of(uploadProductRejected(error)))

它通过按下按钮调用:

      onPress={() => {
       let product = {
              "name": props.name,
              "brand": props.brand,
              "description": props.description,
              "image": "fakeUrl"
          }

        props.uploadProduct(JSON.stringify(product))

这是上述史诗中actionobject的内容:

payload: "{"name":"v","brand":"v","description":"v","image":"fakeUrl"}"
type: "UPLOAD_PRODUCT"

是否因为我的 json 使用了所有没有转义的双引号?

我可以验证史诗中执行 ajax post 的代码行在按下按钮时执行 运行,并且在第一个按钮按下时它会结束调度uploadProductRejected(error),甚至没有发出网络请求,在 uploadProductRejected 操作中发送的错误只是 { } 并且在随后的按钮按下时它甚至从不发送拒绝或完成的操作。

知道为什么它被拒绝,为什么它甚至从未尝试发出网络请求吗?

顺便说一句——不幸的是,您为 Rx.DOM.Request is for v4 of RxJS, but your code is using v5. Documentation for v5 is located here however Observable.ajax is not yet documented 指向的文档,但它非常接近 v4 版本,并且具有最明显的 API.


关于您的代码,我们需要先做几件事。

你可能不应该把 mapcatch 放在 top-level Observable 外面。如果你这样做,你的 mergeMap 中的任何错误都被允许传播出去并到达 action$.ofType,这意味着你的史诗将终止,因为你捕获了错误并从出错的 top-level 链中切换至 Observable.of(uploadProductRejected(error)).

相反,您想通过将逻辑放在 mergeMap:

中来隔离您的 Observables
export const uploadProductEpic = action$ =>
  action$.ofType(UPLOAD_PRODUCT)
    .mergeMap(action => {
      ajax.post(
        'http://192.168.20.3:4000/products', 
        action.payload,
        { 'Content-Type': 'application/json' }
      )
        .map(response => uploadProductFulfilled(response))
        .catch(error => Observable.of(uploadProductRejected(error)))
    });

虽然这只是普通的 RxJS,但在 redux-observable 中这尤其重要,因为您不希望您的史诗在一个请求失败时终止。这被描述为 in the docs here。如果这令人困惑,我建议花一些时间来完全理解 Observable 链是如何工作的。除了阅读文档和教程(很有帮助),还可以在像 jsbin 这样的 REPL 中进行实验。


现在我们已经解决了这个问题,要真正解决您的问题,您需要查看您捕获并发出的实际错误消息是什么 uploadProductRejected()

虽然你没有提供,但我可以根据你的代码猜测它是这样的:

TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. at subscribeToResult

它还会包含一个堆栈跟踪,它应该首先指向类似 MergeMapSubscriber._innerSub 的内容,这意味着它是 mergeMap 运算符抛出此错误。如果我们查看您对 mergeMap 的用法,我们会发现实际上我们没有 returning 任何东西!由于您使用的是带 花括号 的箭头函数,这意味着您需要有一个明确的 return.

export const uploadProductEpic = action$ =>
  action$.ofType(UPLOAD_PRODUCT)
    .mergeMap(action => { // <--------------------------- whoops!
      ajax.post(
        'http://192.168.20.3:4000/products', 
        action.payload,
        { 'Content-Type': 'application/json' })
    })

您可能打算使用不带花括号的箭头函数,因此它具有隐式 return.