• [XState] Invoke with callback


    Invoke not only able to return a promise, but also a callback function with 'sendBack' & 'receive' callbacks

          invoke: {
            // nested state with id reference
            id: "child",
            // return a callback function
            src: (context, event) => (sendBack, receive) => {
              setTimeout(() => {
                // send out a event
                sendBack({
                  type: "I_AM_DONE",
                });
              }, 5000);
               // wait for receiving a event
              receive((event) => {
                console.log("event", event);
                if (event.type === "SNED_IT_ALREADY") {
                  sendBack({
                    type: "I_AM_DONE",
                  });
                }
              });
            },

    Receive a event:

          on: {
            RESOLVE: "resolved",
            // cancel the promise
            CANCEL: "idle",
            I_AM_DONE: "resolved",
            SNED_IT_ALREADY: {
              actions: send(
                {
                  type: "SNED_IT_ALREADY",
                },
                {
                  to: "child",
                }
              ),
            },
          },

    --- Full code---

    import { createMachine, assign, interpret, send } from "xstate";
    
    const elBox = document.querySelector("#box");
    
    const randomFetch = () => {
      return new Promise((res, rej) => {
        setTimeout(() => {
          if (Math.random() < 0.5) {
            rej("Fetch failed!");
          } else {
            res("Fetch succeeded!");
          }
        }, 2000);
      });
    };
    
    const machine = createMachine({
      initial: "idle",
      states: {
        idle: {
          on: {
            FETCH: "pending",
          },
        },
        pending: {
          on: {
            RESOLVE: "resolved",
            // cancel the promise
            CANCEL: "idle",
            I_AM_DONE: "resolved",
            SNED_IT_ALREADY: {
              actions: send(
                {
                  type: "SNED_IT_ALREADY",
                },
                {
                  to: "child",
                }
              ),
            },
          },
          invoke: {
            // Invoke your promise here.
            // The `src` should be a function that returns the source.
            /* Promise
            src: (context, event) => {
              return randomFetch();
            },
            */
            id: "child",
            src: (context, event) => (sendBack, receive) => {
              setTimeout(() => {
                sendBack({
                  type: "I_AM_DONE",
                });
              }, 5000);
    
              receive((event) => {
                console.log("event", event);
                if (event.type === "SNED_IT_ALREADY") {
                  sendBack({
                    type: "I_AM_DONE",
                  });
                }
              });
            },
            onDone: {
              target: "resolved",
            },
            onError: {
              target: "rejected",
            },
          },
        },
        resolved: {
          // Add a transition to fetch again
          on: {
            FETCH: "pending",
          },
        },
        rejected: {
          // After 2s, retry again
          after: {
            2000: {
              target: "pending",
            },
          },
        },
      },
    });
    
    const service = interpret(machine);
    
    service.onTransition((state) => {
      elBox.dataset.state = state.toStrings().join(" ");
    
      console.log(state);
    });
    
    service.start();
    
    elBox.addEventListener("click", (event) => {
      service.send("FETCH");
    });
    
    const cancelBtn = document.querySelector("#cancel");
    cancelBtn.addEventListener("click", (event) => {
      service.send("CANCEL");
    });
    
    const receiveBtn = document.querySelector("#receive");
    receiveBtn.addEventListener("click", (event) => {
      service.send("SNED_IT_ALREADY");
    });
  • 相关阅读:
    自定义MyBatis
    SpringMVC基本
    Struts2访问Servlet
    Struts2的配置
    Rust开发环境搭建
    android webview和 javascript 进行交互
    C#开发step步骤条控件
    如何用cmd命令递归文件夹中的所有特定文件,拷贝到另一个文件夹中
    C#用DesignSurface实现一个简单的窗体设计器
    Roslyn如何实现简单的代码提示
  • 原文地址:https://www.cnblogs.com/Answer1215/p/13496914.html
Copyright © 2020-2023  润新知