【问题标题】:Redux Saga yield call(someAPI) is not waiting for API call to completeRedux Saga yield call(someAPI) 不等待 API 调用完成
【发布时间】:2019-08-09 17:40:50
【问题描述】:

我正在制作一个从 firestore 获取事件对象以将其显示在地图上的应用。

我实现了 redux-saga 对 componentDidMount 上的 firestore API 进行异步调用,以便在地图上显示结果。 我有 3 个操作(LOAD_EVENTS_LOADING/LOAD_EVENTS_SUCCESS/LOAD_EVENTS_ERROR),以便在呈现结果之前显示加载组件。 saga.js:

> import { put, call, takeLatest } from 'redux-saga/effects' import {
> getEventsFromGeoloc }  from '../../firebaseAPI/APImethods'
> 
> function* fetchEvents(action) {
>     try {
> 
>         const events = yield call(getEventsFromGeoloc, {latMarker : action.payload.latMarker, longMarker: action.payload.longMarker,
> circleRadius: action.payload.circleRadius});
>         yield put({type: 'LOAD_EVENTS_SUCCESS', fetchedEvents: events});
>     } catch (e) {
>         yield put({type: 'LOAD_EVENTS_ERROR', error: e.message});
>     } }
> 
> export function* eventsSaga() {
>     yield takeLatest('LOAD_EVENTS_LOADING', fetchEvents); }
> 
>  export default eventsSaga;

我的问题是,在我的传奇中,动作“LOAD_EVENTS_SUCCESS”是在 API 调用结束之前调度的。

如何确保在调度“LOAD_EVENTS_SUCCESS”操作之前完成 API 调用? 感谢您的帮助!

这是我的 API 方法:

import firebase from 'react-native-firebase';
import { GeoFirestore } from 'geofirestore';

export const getEventsFromGeoloc = (payload) => {

    let events =[]
    const geoFirestore = new GeoFirestore(firebase.firestore());
    const geoCollection = geoFirestore.collection('events');
    const query = geoCollection.near({
        center: new firebase.firestore.GeoPoint(payload.latMarker, payload.longMarker),
        radius: payload.circleRadius
    });

    query.get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
            const idEvent = doc.id
            const eventData = doc.data()
            events.push({idEvent, eventData})
        });
    })
    .catch(function(error) {
        console.log("Error getting documents: ", error);
    });

    return events;
}

【问题讨论】:

  • Saga 看起来不错。你肯定会从 getEventsFromGeoloc 返回一个承诺吗?也许你什么都不退回?
  • 嗨,我正在从 getEventsFromGeoloc API 方法返回一个数组
  • 我在getEventsFromGeoloc 的底部看到return events,您可以尝试在收到回复时将其放在.then 中吗?
  • 你整理好了吗?
  • @Adam 是的,我刚刚在下面添加了我的答案。谢谢大家的帮助!

标签: react-native redux-saga


【解决方案1】:

getEventsFromGeoloc 没有返回一个让 redux-saga 等待的承诺,这就是问题所在

只需返回一个通过事件解决的承诺:

export const getEventsFromGeoloc = (payload) => {
    // ...

    return query.get()
    .then(function(querySnapshot) {
        const events = []
        querySnapshot.forEach(function(doc) {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
            const idEvent = doc.id
            const eventData = doc.data()
            events.push({idEvent, eventData})
        });

        return events
    })
    .catch(function(error) {
        console.log("Error getting documents: ", error);
    });
}

【讨论】:

    【解决方案2】:

    call(fn, ...args)
    fn:函数 - 一个生成器函数,或者返回 Promise 作为结果或任何其他值的普通函数。
    Refer this docs

    在你的情况下即使您的响应尚未到达,您也会从您的 getEventsFromGeoloc 函数返回 events

    【讨论】:

      【解决方案3】:

      Firebase 的工作方式与您的预期不同。 firebase 查询会立即返回,它们不会等待查询完成并在返回之前由您的代码处理。

      我最终在自己的应用程序中做的不是从原始 saga 函数调用成功/失败操作,而是从我的查询回调中调用它们,如下所示:

      query.get()
          .then(function(querySnapshot) {
              querySnapshot.forEach(function(doc) {
                  // doc.data() is never undefined for query doc snapshots
                  console.log(doc.id, " => ", doc.data());
                  const idEvent = doc.id
                  const eventData = doc.data()
                  events.push({idEvent, eventData})
              });
              yield put({type: 'LOAD_EVENTS_SUCCESS', fetchedEvents: events});
          })
          .catch(function(error) {
              console.log("Error getting documents: ", error);
              yield put({type: 'LOAD_EVENTS_ERROR', error: error.message});
          });
      

      注意:这还需要您将 getEventsFromGeoloc 函数设为生成器函数或 saga,以使用 yield 语句以及导入 put saga 效果。

      其他注意事项:您可以通过传递成功和失败的回调函数来使函数更通用,并且只需调用回调而不是像这样对您正在调度的操作进行硬编码。或者您可以传入动作类型和有效负载键以在 firebase 的完成回调中构建动作。

      如果这还不够有用,或者如果您对我在这里提出的内容有疑问,请告诉我。

      【讨论】:

      • 谢谢 Doug,我用我的 API 函数 getEventsFromGeoloc 做了一个传奇,我得到了我所期望的 :)
      【解决方案4】:

      感谢大家的回答。我用我的 getEventsFromGeoloc 做了一个传奇,并且查询的产量像我预期的那样工作:它等待完整的查询运行,然后返回事件数组并调度 LOAD_EVENTS_SUCCESS 操作。

      这是我的传奇:

      import { put, takeLatest } from 'redux-saga/effects'
      import firebase from 'react-native-firebase';
      import { GeoFirestore } from 'geofirestore';
      
      function* getEventsFromGeoloc(action)  {
          try{
          let events =[]
          const geoFirestore = new GeoFirestore(firebase.firestore());
          const geoCollection = geoFirestore.collection('events');
          const query = geoCollection.near({
              center: new firebase.firestore.GeoPoint(action.payload.latMarker, action.payload.longMarker),
              radius: action.payload.circleRadius
          });
      
          yield query.get()
          .then(function(querySnapshot) {
              querySnapshot.forEach(function(doc) {
                  // doc.data() is never undefined for query doc snapshots
                  console.log(doc.id, " => ", doc.data());
                  const idEvent = doc.id
                  const eventData = doc.data()
                  events.push({idEvent, eventData})
              })})
              yield put({type: 'LOAD_EVENTS_SUCCESS', fetchedEvents: events});
          }
          catch(error) {
              console.log("Error getting documents: ", error);
              yield put({type: 'LOAD_EVENTS_ERROR', error: error.message});
          }
      }
      
      
      export function* eventsSaga() {
          yield takeLatest('LOAD_EVENTS_LOADING', getEventsFromGeoloc);
      }
      
       export default eventsSaga;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-13
        • 1970-01-01
        • 1970-01-01
        • 2019-04-25
        • 1970-01-01
        • 2020-10-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多