【问题标题】:Why does my fork block if I yield it immediately?如果我立即让出,为什么我的叉子会阻塞?
【发布时间】:2019-01-23 11:38:54
【问题描述】:

我有一个传奇,假设是查询第三方工具来收集 UI 的状态。由于调用数量众多,以及我必须如何构建调用树,我正在尝试使用一种方法来使用 fork 启动请求,从而允许我在拼凑所需调用时并行进行十几个,以及加入分叉调用并收集结果的第二种方法。

我的查询方法应该开始调用,如下所示:

* asyncQuery(action, domain, config) {
   let baseUrl;

   if (config && domain) {
      baseUrl = getBaseUrl(config.deployments, domain);
   }  else {
      baseUrl = yield select(selectUrlForDomain(domain));
   }

   return yield fork(this.doManualGetRequest, action.payload.apiPath, baseUrl);
}


 doManualGetRequest(apiPath, baseUrl) {

     const url = buildUrl(basUrl, apiPath);

     const requestPromise = fetch(url, options)
         .then(checkStatus)
         .then(parseJSON)
         .then((data) => ({ data }))
         .catch((err) => ({ err }));
}

这由一些逻辑调用,该逻辑负责构建请求树,并将每个调用添加到队列中。在调用 joinRequets 之前:

* joinRequests(requestsMap) {
    const results = {}
    const requests = Object.entries(requestsMap)


    join(Object.values(requestsMap));

    for (let i = 0; i < requests.length; i++) {

       const [key, request] = request[i];

       results[key] = request.result();
    }

    return results;
}

经过一些实验后,我发现每次调用 doManualGetRequest 都是阻塞的。具体来说,我可以在我的网络选项卡中观看,因为只有在最后一次调用完成后才进行一次调用,并且我使用了 print 语句和 sleep 来确认在 doManualGetRequest 返回的 promise 完成执行之前不会调用新的 fork。

如果我不在 asyncQuery 中产生 fork 命令,而是在运行 join 命令之前在 joinRequest 中产生一个yield,我会看到所有查询都以适当的异步方式同时发出。

为什么 doManualGetRequest 中的让步会导致阻塞行为?

【问题讨论】:

    标签: javascript asynchronous generator redux-saga


    【解决方案1】:

    yielding a fork in doManualGetRequest 阻塞,因为doManualGetRequest 在返回之前等待分叉进程。这里的文档有点棘手,如果你仔细看你会发现找出原因。

    来自文档:

    所有分叉的任务都附加到它们的父级。当父级终止执行自己的指令体时,它将等待所有分叉任务终止后再返回。

    https://redux-saga.js.org/docs/api/#forkfn-args

    因此,如果您在 yield fork 之后在 doManualGetRequest 中有更多代码,则该代码将在您分叉进程后立即运行。但是,doManualGetRequest 不会返回,直到 fork 完成(或失败)。

    fork 的目的是让您可以附加对异步任务的引用并可能取消它或检查它是否仍在运行。你的情况,你不需要那个功能。 请改用spawn

    来自文档,spawn(fn, ...args)

    与 fork(fn, ...args) 相同,但创建一个分离的任务。分离的任务保持独立于其父任务,并且像顶级任务一样工作。 父级不会等待分离任务终止才返回,所有可能影响父级或分离任务的事件都是完全独立的(错误、取消)。

    https://redux-saga.js.org/docs/api/#spawnfn-args

    【讨论】:

    • 使用 spawn 似乎有完全相同的问题,它仍然阻止我的函数返回,尽管文档说了什么
    猜你喜欢
    • 2020-01-05
    • 2021-04-17
    • 2011-07-04
    • 2011-10-11
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 2019-01-20
    • 2013-04-19
    相关资源
    最近更新 更多