Dva: Model: Cara "menunggu" lebih banyak/grup saga membuat panggilan masuk

Dibuat pada 5 Jul 2017  ·  21Komentar  ·  Sumber: dvajs/dva

Hallo teman-teman,
Dua hari terakhir saya mencari cara bagaimana memanggil effectB, effectC dari ModelB, ModelC di dalam effectA di modelA dan menunggu mereka . Saya membaca masalah (#134, #325, dan banyak lagi) tetapi tidak berhasil menemukan solusi.

Setelah pengguna masuk, saya ingin init beberapa model sebelum menampilkan dasbor.

model aplikasi

* modelsInit({}, { put }) {
   yield put({ type: 'loadingShow' });
   yield put({ type: 'activity/query' });
   yield put({ type: 'xyz.../query' });
   yield put({ type: 'loadingHide' });
},

model aktivitas

  namespace: 'activity',
  .
  .
  .
  effects: {
    * query({ payload }, { call, put }) {
      const response = yield call(activityService.query, parse(payload));
      ...
  },
  .
  .
  .

Karena "put" tidak sinkron, 'loadingHide' sayangnya dipanggil sebelum 'aktivitas/kueri' selesai.

Apakah ada solusi elegan untuk masalah ini?

Terima kasih atas bantuan Anda sebelumnya @sorrycc , @helloyou2012 , @cycgit , @nikogu , @LeuisKen , @nihgwu , @zuiidea , @longzhaobi atau siapa pun ;o).

Komentar yang paling membantu

@vipcxj
```javascript
{
ruang nama: 'app1',
efek: {
* jalankan(param, {pilih, masukkan, panggil, ambil}) {
hasil put({type: 'loadingShow'});
hasil put({type: 'app2/run'});
hasil take('app2/runOk');
hasil put({type: 'app3/run'});
hasil take('app3/runOk');
hasil put({type: 'loadingHide'});
}
},
};
````

```javascript
{
ruang nama: 'app2',
efek: {
* jalankan(param, {pilih, masukkan, panggil}) {
hasil panggilan(...);
hasil put({ketik: 'runOk'});
}
},
};
````

javascript { namespace: 'app3', effects: { * run(param, {select, put, call}) { yield call(...); yield put({type: 'runOk'}); } }, }; ```` 但都避免不了造成阻塞 <strong i="33">@sorrycc</strong> 是否有什么非阻塞的实现方式,我感觉可以从take入手 take 要是支持 `且` 的逻辑关系就可以实现非阻塞了 类似这种 javascript
{
ruang nama: 'app1',
efek: {
* jalankan(param, {pilih, masukkan, panggil, ambil}) {
hasil put({type: 'loadingShow'});
hasil put({type: 'app2/run'});
hasil put({type: 'app3/run'});
hasil take('app2/runOk') && hasil take('app3/runOk')
hasil put({type: 'loadingHide'});
}
},
};
````

Semua 21 komentar

panggilan berlaku menerima fungsi yang mengembalikan janji. efek adalah pembangkit fungsi. jangan menggunakannya sebagai argumen panggilan. Cukup masukkan kode async Anda ke dalam fungsi yang mengembalikan janji, dan gunakan sebagai argumen panggilan yang berlaku.

Terima kasih atas jawabannya @vipcxj.
Saya mencoba melakukan itu sebelumnya tetapi memiliki masalah dengan hasil atau put.

Bisakah Anda memberikan contoh dalam konteks saya?

gunakan put to dispatch reducer, gunakan panggilan untuk memanggil fungsi yang mengembalikan janji.

  • modelInit({ payload }, { put, call }) {
    hasil put({ ketik: 'loadingShow' });
    hasil panggilan(activityService.query, parse(payload));
    hasil put({ ketik: 'xyz.../query' });
    hasil put({ ketik: 'loadingHide' });
    },

Saya tidak ingin memanggil layanan aktivitas di appModel jika saya memiliki layanan yang sudah ditentukan di activityModel dan semua logika berikutnya.
Saya juga tidak ingin menggunakan panggilan balik, terutama jika saya ingin menggunakan sekitar 10+ x "yield put({ type: 'xyz.../query' });"

Saya perlu menelepon

yield put({ type: 'activity/query' });
yield put({ type: 'xyz.../query' });
yield put({ type: 'xyz2.../query' });
.
.
.

dan kemudian (setelah semuanya) atur pemuatan.

yield put({ type: 'loadingHide' });

(sesuatu seperti async/menunggu)

Karena .../query akan mengisi data ke toko, mungkin saya dapat memeriksa semua status yang diperlukan di komponen saya dan jika terisi, kirim tindakan 'loadingHide'. Itu mungkin cara untuk pergi tetapi saya masih tertarik untuk memberi contoh bagaimana menunggu lebih dari satu _ put _ tanpa panggilan balik.

Tidak mungkin, hasil tidak ajaib, itu bergantung pada kerangka kerja bersama. Dalam kerangka kerja bersama, hasil menerima fungsi atau janji.

Menarik.
Terima kasih atas kesabaran dan waktu Anda!

Saya salah. menghasilkan menerima generator, dan efek adalah generator. jadi gunakan panggilan dan berikan panggilan generator fungsi bukan string. seperti ini:
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 tidak membantu, gunakan fungsi efek lain atau tidak tidak masalah hasilnya
dalam kasus saya, saya ingin mendapatkan daftar tugas dan menyimpannya ke model log , kemudian dalam model other dapatkan taskId pertama sebagai param url


log model:

    * 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 model:

    * 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}`));
      }
    },

hasilnya selalu 1 5 2 3 4 , mungkin satu-satunya solusi adalah callback
apakah ini masih menjadi masalah di versi utama berikutnya? @maafcc

@daskyrk gunakan panggilan, bukan put. panggilan untuk fungsi async, lakukan tindakan.

@vipcxj Saya benar-benar menggunakan panggilan, saya mendefinisikan fungsi effect dan yield call(effect) di komentar, maksud saya tidak ada gunanya karena tanpa memanggil fungsi effect apakah ada yang saya salah paham?

       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
{
ruang nama: 'app1',
efek: {
* jalankan(param, {pilih, masukkan, panggil, ambil}) {
hasil put({type: 'loadingShow'});
hasil put({type: 'app2/run'});
hasil take('app2/runOk');
hasil put({type: 'app3/run'});
hasil take('app3/runOk');
hasil put({type: 'loadingHide'});
}
},
};
````

```javascript
{
ruang nama: 'app2',
efek: {
* jalankan(param, {pilih, masukkan, panggil}) {
hasil panggilan(...);
hasil put({ketik: 'runOk'});
}
},
};
````

javascript { namespace: 'app3', effects: { * run(param, {select, put, call}) { yield call(...); yield put({type: 'runOk'}); } }, }; ```` 但都避免不了造成阻塞 <strong i="33">@sorrycc</strong> 是否有什么非阻塞的实现方式,我感觉可以从take入手 take 要是支持 `且` 的逻辑关系就可以实现非阻塞了 类似这种 javascript
{
ruang nama: 'app1',
efek: {
* jalankan(param, {pilih, masukkan, panggil, ambil}) {
hasil put({type: 'loadingShow'});
hasil put({type: 'app2/run'});
hasil put({type: 'app3/run'});
hasil take('app2/runOk') && hasil take('app3/runOk')
hasil put({type: 'loadingHide'});
}
},
};
````

@vipcxj Eh... Apakah saya bisa call efek model lain tanpa mengimpornya ?

Seperti @jindada , @2 serupa dengan cara ini.

@daskyrk semuanya bahasa Cina, jadi saya tidak akan berbicara bahasa burung~ Ada banyak metode, tetapi Anda harus merangkumnya sendiri, dan premisnya adalah Anda bisa mendapatkan model teratas, menguraikan string efek, temukan efeknya di model teratas, dan kemudian berpikir Lakukan apa pun yang Anda inginkan~ Tapi saya tidak tahu apakah saya membuat aplikasi, apakah dva dapat menjamin bahwa aplikasi ini adalah aplikasi yang saya buat, dan tidak akan menyalin yang lain pada suatu waktu, atau dva adalah sudah disediakan dalam model. Buka metode model lain?

@vipcxj sepertinya belum ada. . Tapi saya tidak pernah menggunakan metode take. @jindada maksud Anda menggunakan put asynchronous untuk memanggil efek di model lain, dan kemudian menggunakan blok take synchronous untuk menunggu tindakan di parameter dieksekusi. Saya ingin tahu apakah saya memahaminya, Baik?
Dan kalimat ini: 支持 且 的逻辑关系就可以实现非阻塞了 mengacu pada dua efek asinkron dari 'app2/run' dan 'app3/run' dapat dieksekusi pada saat yang sama, dan kemudian gunakan take untuk menunggu hasilnya secara sinkron?

Hmm, yang saya inginkan secara asinkron adalah turun ketika kedua 'app2/run' dan 'app3/run' dijalankan. Pengambilan saga hanya mendukung logika . nantikan dva@2 bersama

soga, dan lakukan operasi semacam ini, pelajari

@JonasJonny
Put.resolve() diblokir
Misalnya:
yield put.resolve({ type: 'user/fetchCurrent', IdDangVien, });

@mikelhpdatke Terima kasih atas kontribusinya.
Pertanyaannya terhubung dengan DVA v1.xx
Saya tidak yakin tapi saya pikir put.resolve "diaktifkan" dari v2.xx

Bagaimanapun, put.resolve jelas merupakan solusi di v2.

const response = yield put.resolve({
  type: 'nameOfEffect',
  payload: {...},
});

return response;
Apakah halaman ini membantu?
0 / 5 - 0 peringkat