Проблема обратного вызова Redux-Saga, не связанная с ajax

#javascript #reactjs #redux-saga

#javascript #reactjs #redux-saga

Вопрос:

Итак, мне трудно понять, как преобразовать следующий пример для использования sagas, поскольку это не проблема асинхронности, связанная с ajax:

 var dogBarkingBuffer = null;
// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();

function loadDogSound(url) {
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.responseType = 'arraybuffer';

  // Decode asynchronously
  request.onload = function() {
    context.decodeAudioData(request.response, function(buffer) {
      dogBarkingBuffer = buffer;
    }, onError);
  }
  request.send();
}
  

Проблема, которую я обнаружил, заключается не в XMLHttpRequest связанных материалах, а скорее в том, как справиться с decodeAudioData(data, callback) , который выдает вам возвращаемые данные только через обратный вызов, и поэтому я хочу запустить действие i там, чтобы добавить это в мое хранилище Redux.

На данный момент моя saga выглядит так, но недостающий выход перед decodeAudio кажется проблемой:

 import { takeLatest } from "redux-saga";
import { call, put } from "redux-saga/effects";
import axios from "axios";

import * as acts from "actions/playList";


const audioFileRequest = (url) => {
  return axios.get(url, {
    withCredentials: true,
    responseType: "arraybuffer",
  })
  .then(({ data }) => data)
  .catch(({ error }) => error);
};

const decodeAudio = (undecodedData, audioContext) => {
  return audioContext.decodeAudioData(undecodedData, (buffer) => {
    acts.recivedAudioFile(buffer);  // no yeald ???
  });
};

function *fetchAudio({ url, audioContext }) {
  try {
    let rawAudioData = yield call(audioFileRequest, url);
    decodeAudio(rawAudioData, audioContext); // no yield ???
  }
  catch (error) {
    yield put(acts.errorFetchingAudioFile(error));
  }
}

export function *watchFetchAudio() {
  yield takeLatest(acts.AUDIO_FILE_REQUEST, fetchAudio);
}
  

Ответ №1:

Я думаю, вы можете преобразовать функцию декодирования звука с помощью es6-promise и использовать метод вызова redux saga.

 const decodeAudio = ({rawAudioData, audioContext}) => {
    return new Promise((resolve, reject) => {
        audioContext.decodeAudioData(rawAudioData, (buffer) => {
            resolve({buffer}); // or reject if failed
        });
    }).then(({buffer}) => buffer).catch(error => error)
};

function *fetchAudio({ url, audioContext }) {
    try {
        let rawAudioData = yield call(audioFileRequest, url);
        let buffer = yield call(decodeAudio, {rawAudioData, audioContext});
        acts.recivedAudioFile(buffer);
    }
    catch (error) {
        yield put(acts.errorFetchingAudioFile(error));
    }
}
  

Комментарии:

1. При выходе после того, как я написал это и сам подумал об этом. Спасибо за быстрый ответ!

2. Приветствую .. 🙂 @CpILL