React.js告诉您取消承诺。官方承诺无法取消。我该怎么办呢?

为了防止幻像更新未安装的React组件,React会告诉您在卸载时在组件上cancel any pending promises(例如承诺获取其他数据)。使用Bluebird Promise可以很容易地实现这一点,在Bluebird Promise上使用.cancel()方法会使.then().catch()处理程序从不响应。

但是,ES6承诺不支持取消。此外,ES7的asyncawait仅使用本机Promises,不支持任何直接替换(例如Bluebird)。这意味着,如果您想按照他们的指示取消React中的Promises,则必须使用.then().catch(),并且还必须在{ {1}},以便可以将其取消。

这真的是React所期望的吗?

baili251810659 回答:React.js告诉您取消承诺。官方承诺无法取消。我该怎么办呢?

仅供参考。 使用CPromise包,您可以取消承诺链,包括嵌套的承诺链。它支持AbortController和生成器,以替代ECMA异步功能。目前该项目处于测试阶段。

发电机使用情况Live Demo

import CPromise from "c-promise2";

const chain = CPromise.resolve()
  .then(function* () {
    const value1 = yield new CPromise((resolve,reject,{ onCancel }) => {
      const timer = setTimeout(resolve,1000,3);
      onCancel(() => {
        console.log("timer cleared");
        clearTimeout(timer);
      });
    });
    // Run promises in parallel using CPromise.all (shortcut syntax)
    const [value2,value3] = yield [
      CPromise.delay(1000,4),CPromise.delay(1000,5)
    ];
    return value1 + value2 + value3;
  })
  .then(
    (value) => {
      console.log(`Done: ${value}`); // Done: 12 (without calling cancel)
    },(err) => {
      console.log(`Failed: ${err}`); // Failed: CanceledError: canceled
    }
  );

setTimeout(() => chain.cancel(),100);

输出:

timer cleared 
Failed: CanceledError: canceled 

所有阶段都完全可以取消/中止。 这是与React Live Demo

一起使用的示例
export class TestComponent extends React.Component {
  state = {};

  async componentDidMount() {
    console.log("mounted");
    this.controller = new CPromise.AbortController();
    try {
      const json = await this.myAsyncTask(
        "https://run.mocky.io/v3/7b038025-fc5f-4564-90eb-4373f0721822?mocky-delay=2s"
      );
      console.log("json:",json);
      await this.myAsyncTaskWithDelay(1000,123); // just another async task
      this.setState({ text: JSON.stringify(json) });
    } catch (err) {
      if (CPromise.isCanceledError(err)) {
        console.log("tasks terminated");
      }
    }
  }

  myAsyncTask(url) {
    return CPromise.from(function* () {
      const response = yield cpFetch(url); // cancellable request
      return yield response.json();
    }).listen(this.controller.signal);
  }

  myAsyncTaskWithDelay(ms,value) {
    return new CPromise((resolve,ms,value);
      onCancel(() => {
        console.log("timeout cleared");
        clearTimeout(timer);
      });
    }).listen(this.controller.signal);
  }

  render() {
    return (
      <div>
        AsyncComponent: <span>{this.state.text || "fetching..."}</span>
      </div>
    );
  }
  componentWillUnmount() {
    console.log("unmounted");
    this.controller.abort(); // kill all pending tasks
  }
}

Using Hooks and cancel method

import React,{ useEffect,useState } from "react";
import CPromise from "c-promise2";
import cpFetch from "cp-fetch";

export function TestComponent(props) {
  const [text,setText] = useState("fetching...");

  useEffect(() => {
    console.log("mount");
    const promise = cpFetch(props.url)
      .then(function* (response) {
        const json = yield response.json();
        setText(`Delay for 2000ms...`);
        yield CPromise.delay(2000);
        setText(`Success: ${JSON.stringify(json)}`);
      })
      .canceled()
      .catch((err) => {
        setText(`Failed: ${err}`);
      });

    return () => {
      console.log("unmount");
      promise.cancel();
    };
  },[props.url]);

  return <p>{text}</p>;
}
本文链接:https://www.f2er.com/2828656.html

大家都在问