巧妙的Promise执行数据控制

1,097 阅读1分钟
Promise创建及控制执行

const context = [];

function subscribe(running, subscriptions) {
  subscriptions.add(running);
  running.dependencies.add(subscriptions);
}

export function createSignal() {
  const subscriptions = new Set();
  let handler;

  const read = () => {
    const running = context[context.length - 1];
    if (running) subscribe(running, subscriptions);
    return new Promise((r) => handler = r);
  };

  const write = () => {
    for (const sub of [...subscriptions]) {
      sub.execute(handler);
    }
  };
  return [read, write];
}


function cleanup(running) {
  for (const dep of running.dependencies) {
    dep.delete(running);
  }
  running.dependencies.clear();
}

export function createEffect(fn) {
  const execute = (cal) => {
    cleanup(running);
    context.push(running);
    try {
      fn(cal);
    } finally {
      context.pop();
    }
  };

  const running = {
    execute,
    dependencies: new Set()
  };

  execute();
}

利用上述控制我们举一个小例子
const [getPromise, setPromise] = createSignal();
const [getPromise1, setPromise1] = createSignal();

function Grade() {
  const [grade, setGrade] = useState(0);
  const gradeRef = useRef(0);
  gradeRef.current = grade;
  useEffect(() => {
    createEffect((hanlder) => {
      getPromise();
      if (hanlder) {
        setTimeout(() => hanlder(gradeRef.current), 1000)
      }
      console.log('getPromise')
    })
  }, [])

  const handleAdd = () => {
    setGrade(c => c+1);
    getPromise1().then((res) => {
      console.log(res,'res1=====123')
    });
    setPromise1();
  }
  return (
    <div>
      <div>{grade}</div>
      <div onClick={handleAdd}>add</div>
    </div>
  )
}

function Counter() {
  const [count, setCount] = useState(0);

  const countRef = useRef(0);
  countRef.current = count;
  useEffect(() => {
    createEffect((hanlder) => {
      getPromise1();
      if (hanlder) {
        setTimeout(() => hanlder(countRef.current), 1000)
      }
      console.log('getPromise')
    })
  }, [])


  const handleAdd = () => {
    setCount(c => c+1);
    getPromise().then((res) => {
      console.log(res,'res=====123')
    });
    setPromise();
  }
  return (
    <div>
      <div>{count}</div>
      <div onClick={handleAdd}>add</div>
    </div>
  )
}

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Counter />
        <Grade />
      </header>
    </div>
  );
}

从上面一个例子中我们可以完美的跨组件拿到对方异步执行结果,从而做数据处理。这篇文章也是借鉴了我的之前的一篇文章《Solidjs状态更新管理在React中的应用》