2016-02-14 1 views
4

Я работаю над приложением, которое должно управлять большим количеством данных. В процессе инициализации несколько вызовов api должны выполняться, когда пользователь видит панель загрузки.React Redux app - комплексная композиция init action выполняет окончательное обещание перед выполнением остальных

Вот мой инициализации действия:

export function init(key) { 

    return (dispatch, getState) => { 

    // start init 
    dispatch(initStart()); 

    setTimeout(() => { 
     dispatch(initProcess(10)); 
    }, 0) 


    return Promise.all([ 

     // load users 
     dispatch(loadUsers(key)).then(() => { 
     dispatch(initProcess(30)); 
     }), 

     // load other stuff 
     // ... 

     // load articles 
     dispatch(loadArticles(key)).then(() => { 
     dispatch(initProcess(60)); 
     }), 

    // should be executed after all actions/reducers are done 
    ]).then(() => { 
     setTimeout(() => { 
     dispatch(initFinish()); 
     }, 700); 
    }); 
    } 
} 

До сих пор он прекрасно работает, но будет 20к до 50к статей. Бэкэнд должен выполнить некоторые объединения, чтобы собрать данные вместе, поэтому я уверен, что я получу тайм-аут сервера, если попытаюсь получить их в один кусок.

Идея состоит в том, чтобы сначала получить общее число, а затем получить статьи в 1 кусочках в цикле. Но это не будет работать так, как мне нужно. Я получаю initFinish, отправленный после подсчета статей, но не после их получения.

Вот loadArticles действие:

export function loadArticles(key) { 
    return (dispatch, getState) => { 

    // check local db first 

    // get total number 
    return dispatch(countArticles(key)) 
    .then(result => { 
     Promise.all([ 
     // No idea how to put the loop in here :(
     dispatch(fetchArticles(key, 1000)), 
     ]) 
    }); 
} 

}

У меня нет цикла, но пока это еще не точка. Логика остается прежней. Я возвращаю dispatch(countArticles(key)) до fetchArticles.

У кого-нибудь есть подсказка? Это было бы круто.


РЕДАКТИРОВАТЬ

coutArticles и fetchArticles

function countArticles(key) { 
    return { 
    [CALL_API]: { 
     types: [ COUNT_ARTICLES_REQUEST, COUNT_ARTICLES_SUCCESS, COUNT_ARTICLES_FAILURE ], 
     endpoint: `articles`, 
     schema: Schemas.ARTICLE_COUNTER 
    } 
    } 
} 
function fetchArticles(key, take, skip) { 
    return { 
    [CALL_API]: { 
     types: [ FETCH_ARTICLES_REQUEST, FETCH_ARTICLES_SUCCESS, FETCH_ARTICLES_FAILURE ], 
     endpoint: `articles/${take}/${skip}`, 
     schema: Schemas.ARTICLE_ARRAY 
    } 
    } 
} 

Промежуточное это те же эс here


2. РЕДАКТИРОВАТЬ

если я изменить

// get total number 
return dispatch(countArticles(key)) 
.then(result => { 
    Promise.all([ 
    // No idea how to put the loop in here :(
    dispatch(fetchArticles(key, 1000)), 
    ]) 
}); 

в

// get total number 
dispatch(countArticles(key)) 
.then(result => { 
    return Promise.all([ 
    // No idea how to put the loop in here :(
    dispatch(fetchArticles(key, 1000)), 
    ]) 
}); 

я Uncaught TypeError: Cannot read property 'then' of undefined на dispatch(loadArticles(key)).


3.EDIT

Несколько дней спустя я все еще борется ^^

Вот упрощенная функция инициализации, которая должна (только) получить результат подсчета, а затем извлечь статьи:

Но для теперь им неудачу уже здесь:

export function init(key) { 

    return (dispatch, getState) => { 

    countArticles(key).then(result => { 
     console.log(result); 
    }); 

    } 
} 

Выход:

Uncaught TypeError: countArticles(...).then is not a function 
+0

Попробуйте переместить 'return' в' 'диспетчер'' внутри' Promise.all' – Mike

+0

исправьте меня если я ошибаюсь, но 'Promise.all' принимает массив. 'return' в качестве значения массива будет синтаксической ошибкой?! –

+0

Да, вы правы. Я не думал, что все это происходит через: P – Mike

ответ

1

У меня были проблемы с отправкой цепочек; он должен вернуть Promise, но я не мог заставить его работать.

Так что я бы изменить логику таким образом

countArticles(key).then(result => { 
    dispatch({ 
     type: RECEIVED_NUM_ARTICLES, 
     value: result 
    }) 
    Promise.all([...Array(Math.floor(result/1000))].map(_ => 
     fetchArticles(key,1000).then(res => dispatch({ 
      type: RECEIVED_1000_ARTICLES, 
      value: res 
     }) 
    )).then(_ => dispatch({ 
      type: RECEIVED_EVERYTHING 
      value: 'whatever' 
     }) 
    ) 
) 

(я не проверял этот код)

, но в основном: fetch затем dispatch результатом, то цепь другой выборки последовательность/отправка и т.п. ..

потребности цикла переделки для выборки по модулю

преимущество такого подхода заключается в том, что вы можете вверх укажите пользовательский интерфейс с количеством статей, если у вас есть, затем укажите обновления на каждые 1000 статей и, наконец, сообщите, когда они сделаны.

+0

Я знаю, вы сказали, что его не тестировали, но если это что-то вроде 'return dispatch (countArticles (key)), тогда ...' потому что я получаю сообщение об ошибке 'countArticles (...), то это не функция' –

+0

О, я думаю, вы сосредоточились на но это не моя основная проблема. На самом деле это сейчас не проблема. У меня возникают проблемы с порядком отправленных действий. –

+0

Разве 'countArticles' не возвращает' Promise' после вызова Ajax? –

Смежные вопросы