Dva: Looking for a suggestion of using callback promise with DVA

Created on 18 Feb 2019  ·  2Comments  ·  Source: dvajs/dva

Hi guys)

Could someone suggest me how I can call a callback promise ?
I use react-native-fs and downloadFile func.
This from RNFS documentation:

 downloadFile(options: DownloadFileOptions): { jobId: number, promise: Promise<DownloadResult> }
 type DownloadFileOptions = {
   fromUrl: string;          // URL to download file from
   toFile: string;           // Local filesystem path to save the file to
   progress?: (res: DownloadProgressCallbackResult) => void;  // I need to call this with DVA
 };

where progress is callback

and this is my code of the file download from DVA model:

*download({payload}, {call, put}) {
    const {url} = payload;
    const filePath = RNFS.CachesDirectoryPath + '/test.pdf';
    const download = RNFS.downloadFile({
        fromUrl: url,
        toFile: filePath,
        progress  // <-- How do I call the progress callback here with DVA ?
    });
    yield call(download.promise);
}

Most helpful comment

@xiaosongxiaosong thanks for reply and solutions!
The second case looks interesting!
I've resolved that with saga channel. It works even with multi files download.
I leave my solution below, maybe it will help someone.

import {channel} from 'redux-saga';
const downloadFileChannel = channel();

export default {
effects: {
*download({ payload }, { call, put }) {
      const { url } = payload;
      const filePath = RNFS.CachesDirectoryPath + '/test.pdf';
      const download = RNFS.downloadFile({
        fromUrl: url,
        toFile: filePath,
        progress: (progress) => downloadFileChannel.put({type: 'S_PROGRESS', payload: {progress}})
      });
      yield call(download.promise);
    },
},
//Progress watcher.
watch: [
            function* watch({take, call, put}) {
                while (true) {
                    const action = yield take(downloadFileChannel);
                    const  {progress} = action.payload;
                    const p = progress.bytesWritten / progress.contentLength;
                    //yield put({type: 'xxx'}) // Update your state or do something;
                }
            },
            {type: 'watcher'},
        ],
}

All 2 comments

    *download({ payload }, { call, put }) {
      const { url } = payload;
      const filePath = RNFS.CachesDirectoryPath + '/test.pdf';
      function* progress() {
        // yield put({ type: 'xxx' })
      }
      const download = RNFS.downloadFile({
        fromUrl: url,
        toFile: filePath,
        progress, // <-- How do I call the progress callback here with DVA ?
      });
      yield call(download.promise);
    },

or

const eventTarget = (() => {
  let handle;
  const off = () => (handle = undefined);
  return {
    on(fn) {
      handle = fn;
      return off;
    },
    off,
    trigger(e) {
      if (handle) {
        handle(e);
      }
    },
  };
})();

export default {

  subscriptions: {
    setup({ dispatch }) {
      return eventTarget.on(dispatch);
    },
  },

  effects: {
    // eslint-disable-next-line no-unused-vars
    *download({ payload }, { call, put }) {
      const { url } = payload;
      const filePath = RNFS.CachesDirectoryPath + '/test.pdf';
      const download = RNFS.downloadFile({
        fromUrl: url,
        toFile: filePath,
        progress: () => {
          eventTarget.trigger({ type: 'xxx' });
        }, // <-- How do I call the progress callback here with DVA ?
      });
      yield call(download.promise);
    },
  },
};

@xiaosongxiaosong thanks for reply and solutions!
The second case looks interesting!
I've resolved that with saga channel. It works even with multi files download.
I leave my solution below, maybe it will help someone.

import {channel} from 'redux-saga';
const downloadFileChannel = channel();

export default {
effects: {
*download({ payload }, { call, put }) {
      const { url } = payload;
      const filePath = RNFS.CachesDirectoryPath + '/test.pdf';
      const download = RNFS.downloadFile({
        fromUrl: url,
        toFile: filePath,
        progress: (progress) => downloadFileChannel.put({type: 'S_PROGRESS', payload: {progress}})
      });
      yield call(download.promise);
    },
},
//Progress watcher.
watch: [
            function* watch({take, call, put}) {
                while (true) {
                    const action = yield take(downloadFileChannel);
                    const  {progress} = action.payload;
                    const p = progress.bytesWritten / progress.contentLength;
                    //yield put({type: 'xxx'}) // Update your state or do something;
                }
            },
            {type: 'watcher'},
        ],
}
Was this page helpful?
0 / 5 - 0 ratings