Javascript 如何使用带有react挂钩的互斥锁?
我想确保代码块不会并发运行。异步互斥体库似乎不适合我。这里有一个最小的复制:Javascript 如何使用带有react挂钩的互斥锁?,javascript,react-hooks,async-mutex,Javascript,React Hooks,Async Mutex,我想确保代码块不会并发运行。异步互斥体库似乎不适合我。这里有一个最小的复制: /* eslint-disable */ import React, { useState, useEffect } from "react"; var Mutex = require("async-mutex").Mutex; const Timer = () => { const [isActive, setIsActive] = useState(false);
/* eslint-disable */
import React, { useState, useEffect } from "react";
var Mutex = require("async-mutex").Mutex;
const Timer = () => {
const [isActive, setIsActive] = useState(false);
const mutex = new Mutex();
useEffect(() => {
mutex.runExclusive(async function () {
console.log("starting", isActive);
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log("ending", isActive);
});
}, [isActive]);
return (
<div className="app">
<button onClick={() => setIsActive((prev) => !prev)} type="button">
{isActive ? "Active" : "Inactive"}
</button>
</div>
);
};
export { Timer as default };
你可以看到这些是交错的
我如何才能强制它不同时运行?问题很可能是因为每次重新渲染时都会分配互斥,从而为您提供一个新实例
const mutex=new mutex()代码>从组件中删除,为所有计时器组件提供一个全局版本,这意味着计时器可能会相互阻塞
React.usemo
hook中,可以使互斥实例在整个重新渲染过程中保持稳定,这将使每个计时器组件都有自己的互斥,这意味着计时器不能相互阻止,只能阻止其自身
const mutex=React.usemo(()=>new mutex(),[]);
然后将互斥体添加到useffect
中的依赖项数组中:
useffect(()=>{
//你的代码
},[isActive,mutex]);
问题最有可能是因为每次重新渲染时都会分配互斥,从而为您提供一个新实例
const mutex=new mutex()代码>从组件中删除,为所有计时器组件提供一个全局版本,这意味着计时器可能会相互阻塞
React.usemo
hook中,可以使互斥实例在整个重新渲染过程中保持稳定,这将使每个计时器组件都有自己的互斥,这意味着计时器不能相互阻止,只能阻止其自身
const mutex=React.usemo(()=>new mutex(),[]);
然后将互斥体添加到useffect
中的依赖项数组中:
useffect(()=>{
//你的代码
},[isActive,mutex]);
import React,{useState,useffect,useRef,usemo}来自“React”;
var Mutex=require(“异步互斥”).Mutex;
常量计时器=()=>{
常量[isActive,setIsActive]=useState(false);
const mutex=useRef(new mutex());
//或者换一种方式,它可能会更有表现力,
//虽然互斥类有一个几乎为空的构造函数
//const mutex=usemo(()=>new mutex(),[]);
useffect(()=>{
mutex.current.runExclusive(异步函数(){
console.log(“启动”,isActive);
等待新承诺((resolve)=>setTimeout(resolve,1000));
console.log(“结束”,isActive);
});
},[i活跃];
返回(
setIsActive((prev)=>!prev)}type=“button”>
{isActive?“Active”:“Inactive”}
);
};
导出{Timer as default};
如果要取消上一个函数调用并支持卸载时异步例程清理():
/*eslint禁用*/
从“React”导入React,{useState,useffect};
从“c-promise2”导入CPromise;
从“use-async-effect2”导入{UseAncyEffect,UseAncyCallback};
导出默认函数计时器(){
常量[isActive,setIsActive]=useState(false);
const callback=useAncyncCallback(
函数*(){
console.log(“启动”,isActive);
收益率c减少延迟(1000);
console.log(“结束”,isActive);
},
{combine:true}
);
使用异步效应(
函数*(){
控制台日志(“安装”);
屈服回调();
},
[活动]
);
返回(
setIsActive((prev)=>!prev)}type=“button”>
{isActive?“Active”:“Inactive”}
);
}
import React,{useState,useffect,useRef,usemo}来自“React”;
var Mutex=require(“异步互斥”).Mutex;
常量计时器=()=>{
常量[isActive,setIsActive]=useState(false);
const mutex=useRef(new mutex());
//或者换一种方式,它可能会更有表现力,
//虽然互斥类有一个几乎为空的构造函数
//const mutex=usemo(()=>new mutex(),[]);
useffect(()=>{
mutex.current.runExclusive(异步函数(){
console.log(“启动”,isActive);
等待新承诺((resolve)=>setTimeout(resolve,1000));
console.log(“结束”,isActive);
});
},[i活跃];
返回(
setIsActive((prev)=>!prev)}type=“button”>
{isActive?“Active”:“Inactive”}
);
};
导出{Timer as default};
如果要取消上一个函数调用并支持卸载时异步例程清理():
/*eslint禁用*/
从“React”导入React,{useState,useffect};
从“c-promise2”导入CPromise;
从“use-async-effect2”导入{UseAncyEffect,UseAncyCallback};
导出默认函数计时器(){
常量[isActive,setIsActive]=useState(false);
const callback=useAncyncCallback(
函数*(){
console.log(“启动”,isActive);
收益率c减少延迟(1000);
console.log(“结束”,isActive);
},
{combine:true}
);
使用异步效应(
函数*(){
控制台日志(“安装”);
屈服回调();
},
[活动]
);
返回(
setIsActive((prev)=>!prev)}type=“button”>
{isActive?“Active”:“Inactive”}
);
}
starting
true
starting
false
starting
true
ending
true
ending
false
import React, { useState, useEffect, useRef, useMemo} from "react";
var Mutex = require("async-mutex").Mutex;
const Timer = () => {
const [isActive, setIsActive] = useState(false);
const mutex = useRef(new Mutex());
// Or another way, it might be a bit more performant,
// although the Mutex class has an almost empty constructor
// const mutex= useMemo(()=> new Mutex(), []);
useEffect(() => {
mutex.current.runExclusive(async function () {
console.log("starting", isActive);
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log("ending", isActive);
});
}, [isActive]);
return (
<div className="app">
<button onClick={() => setIsActive((prev) => !prev)} type="button">
{isActive ? "Active" : "Inactive"}
</button>
</div>
);
};
export { Timer as default };
/* eslint-disable */
import React, { useState, useEffect } from "react";
import CPromise from "c-promise2";
import { useAsyncEffect, useAsyncCallback } from "use-async-effect2";
export default function Timer() {
const [isActive, setIsActive] = useState(false);
const callback = useAsyncCallback(
function* () {
console.log("starting", isActive);
yield CPromise.delay(1000);
console.log("ending", isActive);
},
{ combine: true }
);
useAsyncEffect(
function* () {
console.log("mount");
yield callback();
},
[isActive]
);
return (
<div className="app">
<button onClick={() => setIsActive((prev) => !prev)} type="button">
{isActive ? "Active" : "Inactive"}
</button>
</div>
);
}