在redux-saga中fork和spawn的区别是什么?

时间:2017-04-06 15:20:32

标签: redux-saga

docs说fork是一个附加的fork ,spawn是一个分离的fork - 它们有什么不同?

2 个答案:

答案 0 :(得分:22)

查看它的一种方法是将您的传奇视为图表。 '叉'从调用进程创建一个子进程。虽然'产生'在图的根部创建一个新子项。

所以,当你' fork'另一个过程,父进程将等到“分叉”。过程结束了。此外,每个例外都会从孩子到父母一起冒出来,并且可以在父母中被捕获。

A'产生'过程虽然不会阻止父母,所以接下来的收益'立即调用语句。此外,父进程将无法捕获在“生成”中发生的任何异常。过程

我希望这很有帮助。

答案 1 :(得分:15)

在相同的文档中说:

  

当父进程终止执行自己的指令体时,它将等待所有分叉任务在返回之前终止。

我们假设我们有这样的设置,在执行流程的中间,我们称fetchAll()可能会调用forkspawn

const { delay, runSaga } = require("redux-saga");
const fetch = require("node-fetch");
const { fork, spawn, call, put} = require("redux-saga/effects");


function* fetchResource(resource) {
    console.log(`Fetch ${resource} start`);
    const response = yield call(fetch, "https://jsonplaceholder.typicode.com" + resource);
    const text = yield call(response.text.bind(response));
    console.log(`Fetch ${resource} end`);
}

function* fetchAll() {
    console.log("Fork or Spawn start");
    // this is pseudo code, I mean here that you can use either
    // fork or spawn, check results below
    const task1 = yield fork||spawn(fetchResource, "/posts/1"); 
    const task2 = yield fork||spawn(fetchResource, "/posts/2");
    console.log("Fork or Spawn end");
}

function* main() {
    console.log("Main start");
    yield call(fetchAll);
    console.log("Main end");
}

runSaga({}, main);

// RESULTS WITH FORK():   |  RESULTS WITH SPAWN():
//                        |
// Main start             |  Main start
// Fork start             |  Spawn start
// Fetch /posts/1 start   |  Fetch /posts/1 start
// Fetch /posts/2 start   |  Fetch /posts/2 start
// Fork end               |  Spawn end
// Fetch /posts/2 end     |  Main end <-- 
// Fetch /posts/1 end     |  Fetch /posts/2 end
// Main end <--           |  Fetch /posts/1 end

我们看到,在call上下文中,fork是non-blocking,但是call在完成所有子进程之后才会完成,因为call本身是阻挡效应。

如果你在另一个fork内调用fork,你就不会看到相同的内容,因为fork本身是非阻塞的,而内部分叉的进程将leak从外部fork进程,但将保存在最近的阻塞上下文中。这是attachment to parent的本质。

因此父yield call(forkedProcess)具有阻塞性质将等待returnthrow resolution个子for​​k进程。

spawn()不是这种情况,因为spawn与封闭的父进程分离,即附加到根进程,因此本地parent不必等待。< / p>

希望这能澄清一点。