Привет ребята,
Последние два дня я искал способ, как вызвать effectB, effectC из ModelB, ModelC внутри effectA в modelA и ждать их . Я читал проблемы (№ 134, № 325 и многие другие), но мне не удалось найти решение.
После входа в систему я хочу запустить несколько моделей, прежде чем показывать панель инструментов.
appModel
* modelsInit({}, { put }) {
yield put({ type: 'loadingShow' });
yield put({ type: 'activity/query' });
yield put({ type: 'xyz.../query' });
yield put({ type: 'loadingHide' });
},
activityModel
namespace: 'activity',
.
.
.
effects: {
* query({ payload }, { call, put }) {
const response = yield call(activityService.query, parse(payload));
...
},
.
.
.
Поскольку "put" является асинхронным, "loadingHide", к сожалению, вызывается до завершения "activity / query".
Есть ли изящное решение этой проблемы?
Заранее благодарим вас за помощь @sorrycc , @ helloyou2012 , @cycgit , @nikogu , @LeuisKen , @nihgwu , @zuiidea , @longzhaobi или кого-либо еще; o).
вызов фактически принимает функцию, которая возвращает обещание. эффект - генератор функций. не используйте его как аргумент вызова. Просто поместите свой асинхронный код в функцию, которая возвращает promist, и используйте его в качестве аргумента вызова в действительности.
Спасибо за ответ @vipcxj.
Я пытался сделать это раньше, но у меня проблема с yield или put.
Можете ли вы привести пример в моем контексте?
используйте put для отправки reducer, используйте call для вызова функции, которая возвращает обещание.
Я не хочу вызывать службу активности в appModel, если у меня есть служба, уже определенная в activityModel, и вся следующая логика.
Также я не хочу использовать обратный вызов, особенно если я хочу использовать около 10+ x "yield put ({type: 'xyz ... / query'});"
Мне нужно позвонить
yield put({ type: 'activity/query' });
yield put({ type: 'xyz.../query' });
yield put({ type: 'xyz2.../query' });
.
.
.
а потом (после всех) установить загрузку.
yield put({ type: 'loadingHide' });
(что-то вроде async / await)
Поскольку ... / query заполнит данные в хранилище, возможно, я смогу проверить все необходимые состояния в моем компоненте и, если он заполнен, отправить действие 'loadingHide'. Возможно, это выход, но мне все же интересно, как ждать более одного _ put _ без обратного вызова.
Это невозможно, yield - это не волшебство, это полагается на ко-фреймворк. В рамках co, yield принимает функцию thunk или обещание.
Интересно.
Спасибо за терпение и время!
Я не прав. yield accept генератор, а эффект - генератор. поэтому используйте вызов и вызовите генератор функций, а не строку. именно так:
javascript
const effect= function * effect({ payload }, { put, call, select }) {
yield put ...
yield call ...
yield select ...
...
}
const model = {
effects: {
effect,
anotherEffect: *(action, { put, call, select }) {
const payloadForEffect = ...
yield call(effect, { payload: payloadForEffect }, { put, call, select });
}
}
}
@vipcxj это бесполезно, используйте другую функцию эффекта или нет, результат не имеет значения
в моем случае я хочу получить список задач и сохранить его в модели log
, а затем в модели other
получить первый taskId в качестве параметра URL
log
модель:
* getLogTaskList({ payload: { buildId } }, { call, update }) {
console.log('2. before inner fetch');
const { tasks: taskList } = yield call(LogServices.getLogTaskList, buildId);
console.log('3. before inner update');
yield update({ taskList });
console.log('4. after inner update');
},
other
модель:
* jumpToLogTask({ payload: { buildId } }, {put, select }) {
console.log('1. outer fetch');
yield put('log/getLogTaskList', { buildId });
console.log('5. outer select taskList');
const taskList = yield select(state => state.log.taskList);
// or use effect function
// const effect = function*() {
// console.log('1. outer fetch');
// yield put('log/getLogTaskList', { buildId });
// console.log('5. outer select taskList');
// const taskList = yield select(state => state.log.taskList);
// };
// yield call(effect);
if (taskList.length) {
yield put(routerRedux.push(`/log/${taskList[0].id}`));
}
},
результат всегда 1 5 2 3 4
, возможно, единственное решение - обратный вызов
Будет ли это проблемой в следующей основной версии? @sorrycc
@daskyrk используйте call, а не put. вызовите асинхронную функцию, положите на действие.
@vipcxj Я действительно использовал call, я определил функцию effect
и yield call(effect)
в комментарии, я имею в виду, что это бесполезно, так как без вызова функции effect
есть что-то, что я неправильно понял?
const effect = function*() {
console.log('1. outer fetch');
yield put('log/getLogTaskList', { buildId }); //don't use put, use call, and don't use string as argument, use function generator.
console.log('5. outer select taskList');
const taskList = yield select(state => state.log.taskList);
};
@vipcxj你 的 这种 方式 会 造成 大量 的 重复 逻辑 我 是 这种 方式 实现 的
`` javascript
{
пространство имен: 'app1',
эффекты: {
* run (param, {выбрать, поставить, позвонить, взять}) {
yield put ({тип: 'loadingShow'});
yield put ({тип: 'app2 / run'});
yield take ('приложение2 / runOk');
yield put ({тип: 'app3 / run'});
yield take ('приложение3 / runOk');
yield put ({type: 'loadingHide'});
}
},
};
`` ''
`` javascript
{
пространство имен: 'app2',
эффекты: {
* run (param, {выбрать, поставить, позвонить}) {
yield call (...);
yield put ({тип: 'runOk'});
}
},
};
`` ''
javascript
{
namespace: 'app3',
effects: {
* run(param, {select, put, call}) {
yield call(...);
yield put({type: 'runOk'});
}
},
};
````
但都避免不了造成阻塞 <strong i="33">@sorrycc</strong> 是否有什么非阻塞的实现方式,我感觉可以从take入手 take 要是支持 `且` 的逻辑关系就可以实现非阻塞了 类似这种
javascript
{
пространство имен: 'app1',
эффекты: {
* run (param, {выбрать, поставить, позвонить, взять}) {
yield put ({тип: 'loadingShow'});
yield put ({тип: 'app2 / run'});
yield put ({тип: 'app3 / run'});
yield take ('app2 / runOk') && yield take ('app3 / runOk')
yield put ({type: 'loadingHide'});
}
},
};
`` ''
@vipcxj Эх ... Есть ли call
эффекта другой модели без его импорта?
Подобно @jindada , @ 2 похожа в этом смысле.
@daskyrk в любом случае весь китайский, поэтому я не буду говорить на птичьем языке ~ Есть много методов, но вы должны инкапсулировать их самостоятельно, и предпосылка состоит в том, что вы можете получить топ-модель, проанализировать строку эффекта, найти эффект в топ-модель, а затем подумайте: делайте все, что хотите ~ Но я не знаю, создаю ли я приложение, могу ли dva гарантировать, что это приложение является приложением, которое я создал, и не будет копировать другое в какое-то время, или dva уже предусмотрено в модели. Перейти к другим методам модели?
@vipcxj, похоже, еще нет. . Но я никогда не использовал метод take. @Jindada вы хотите использовать асинхронно put для вызова эффекта в других моделях, а затем используйте синхронный блок take, чтобы дождаться выполнения действия в параметре. Интересно, понимаю ли я это, Правильно?
И это предложение: 支持 且 的逻辑关系就可以实现非阻塞了
относится к двум асинхронным эффектам: «app2 / run» и «app3 / run» могут выполняться одновременно, а затем использовать take для синхронного ожидания результата?
Хм, я хочу, чтобы асинхронно спускалось вниз, когда выполняются оба'app2 / run 'и'app3 / run'. Дубль саги поддерживает только логику 且
或
且
. Давайте с нетерпением жду два @ 2 вместе
сога, и взяли такую операцию, научились
@JonasJonny
Put.resolve () заблокирован
Например:
yield put.resolve({
type: 'user/fetchCurrent',
IdDangVien,
});
@mikelhpdatke Спасибо за ваш вклад.
Вопрос был связан с DVA v1.xx
Я не уверен, но думаю, что put.resolve
"включен" с версии v2.xx
В любом случае, put.resolve
определенно является решением в версии 2.
const response = yield put.resolve({
type: 'nameOfEffect',
payload: {...},
});
return response;
Самый полезный комментарий
@vipcxj你 的 这种 方式 会 造成 大量 的 重复 逻辑 我 是 这种 方式 实现 的
`` javascript
{
пространство имен: 'app1',
эффекты: {
* run (param, {выбрать, поставить, позвонить, взять}) {
yield put ({тип: 'loadingShow'});
yield put ({тип: 'app2 / run'});
yield take ('приложение2 / runOk');
yield put ({тип: 'app3 / run'});
yield take ('приложение3 / runOk');
yield put ({type: 'loadingHide'});
}
},
};
`` ''
`` javascript
{
пространство имен: 'app2',
эффекты: {
* run (param, {выбрать, поставить, позвонить}) {
yield call (...);
yield put ({тип: 'runOk'});
}
},
};
`` ''
javascript { namespace: 'app3', effects: { * run(param, {select, put, call}) { yield call(...); yield put({type: 'runOk'}); } }, }; ```` 但都避免不了造成阻塞 <strong i="33">@sorrycc</strong> 是否有什么非阻塞的实现方式,我感觉可以从take入手 take 要是支持 `且` 的逻辑关系就可以实现非阻塞了 类似这种
javascript{
пространство имен: 'app1',
эффекты: {
* run (param, {выбрать, поставить, позвонить, взять}) {
yield put ({тип: 'loadingShow'});
yield put ({тип: 'app2 / run'});
yield put ({тип: 'app3 / run'});
yield take ('app2 / runOk') && yield take ('app3 / runOk')
yield put ({type: 'loadingHide'});
}
},
};
`` ''