Redux-observable POST ajax请求永远不会发送网络请求

Ben*_*ins 1 rxjs reactjs react-native redux redux-observable

我有这个redux-observable史诗,它POST是我的后端的json身体,但它实际上从来没有发送到实际的网络请求.它使用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)))
Run Code Online (Sandbox Code Playgroud)

它按下按钮调用:

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

        props.uploadProduct(JSON.stringify(product))
Run Code Online (Sandbox Code Playgroud)

这是action上述史诗中对象的内容:

payload: "{"name":"v","brand":"v","description":"v","image":"fakeUrl"}"
type: "UPLOAD_PRODUCT"
Run Code Online (Sandbox Code Playgroud)

是因为我的json使用所有双引号而没有逃脱?

我可以验证按下按钮时执行ajax post的epic中的代码行,并且按下它的第一个按钮结束调度uploadProductRejected(error),甚至没有发出网络请求,以及在哪里发送错误uploadProductRejected行动是公正的,{ }并且在随后的按钮按下时,它甚至不会发送被拒绝或已完成的动作.

知道它被拒绝的原因,以及为什么它甚至都没有尝试过网络请求?

jay*_*lps 6

顺便说一句 - 您指向的文档Rx.DOM.Request是针对Vx的RxJS,但您的代码使用的是v5.v5的文档位于此处,但遗憾的Observable.ajax尚未记录,但它与v4版本非常接近,并且有一个非常明显的API.


关于你的代码,我们需要先做几件家务.

你可能不应该把它mapcatch外部放在顶级的Observable上.如果你这样做,你内部的任何错误都会mergeMap被传播出去并达到action$.ofType,这意味着你的史诗会终止,因为你捕获了错误,而是从错误的顶级链转换到Observable.of(uploadProductRejected(error)).

相反,您希望通过将该逻辑置于以下内容中来隔离您的Observable mergeMap:

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)))
    });
Run Code Online (Sandbox Code Playgroud)

虽然这只是普通的RxJS,但在redux-observable中,这一点尤为重要,因为您不希望epic在一个请求失败时终止.这在文档中描述.如果这令人困惑,我建议花些时间充分了解Observable链的工作原理.除了阅读文档和教程(有用)之外,还可以像jsbin一样在REPL中进行实验.


现在我们已经完全解决了您的问题,您需要查看您捕获和发出的实际错误消息uploadProductRejected().

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

TypeError:您提供了"undefined",其中包含了一个流.您可以提供Observable,Promise,Array或Iterable.在subscribeToResult

它还包括一个堆栈跟踪,它应首先指向类似的东西MergeMapSubscriber._innerSub,这意味着它mergeMap是抛出此错误的运算符.如果我们看看你的使用情况,mergeMap我们可以看到实际上我们没有返回任何东西!由于您使用带花括号的箭头功能,这意味着您需要具有明确的功能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' })
    })
Run Code Online (Sandbox Code Playgroud)

您可能打算使用不带花括号的箭头函数,以便它具有隐式返回.