docs说fork是一个附加的fork ,spawn是一个分离的fork - 它们有什么不同?
答案 0 :(得分:22)
查看它的一种方法是将您的传奇视为图表。 '叉'从调用进程创建一个子进程。虽然'产生'在图的根部创建一个新子项。
所以,当你' fork'另一个过程,父进程将等到“分叉”。过程结束了。此外,每个例外都会从孩子到父母一起冒出来,并且可以在父母中被捕获。
A'产生'过程虽然不会阻止父母,所以接下来的收益'立即调用语句。此外,父进程将无法捕获在“生成”中发生的任何异常。过程
我希望这很有帮助。
答案 1 :(得分:15)
在相同的文档中说:
当父进程终止执行自己的指令体时,它将等待所有分叉任务在返回之前终止。
我们假设我们有这样的设置,在执行流程的中间,我们称fetchAll()
可能会调用fork
或spawn
:
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)
具有阻塞性质将等待return
或throw resolution
个子fork进程。
但spawn()
不是这种情况,因为spawn与封闭的父进程分离,即附加到根进程,因此本地parent
不必等待。< / p>
希望这能澄清一点。