使用 Promise 检查是否已生成新的随机数
Using a Promise to check if a new random number has been generated
我正在使用 Chainlink Oracles 获取随机数。这个获取随机数的过程需要一段时间。为此,我必须执行这一行(异步调用),它调用我的智能合约的一个函数并存储新的随机数:
const newRandomNumber = await contract.connect(signer).randomResult();
我想要的是使这个过程自动化:当生成一个新号码(并且可以使用)时,我想向用户显示一条消息(在我的前面)。
Hey, a new number has been generated.
如何定期检查 newRandomNumber
中存储的结果是否已更改?当发生这种情况时,我如何显示消息?
因为您在问题上标记了 React,所以这里有一个使用 React 状态的注释示例:
<div id="root"></div><script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/standalone@7.16.6/babel.min.js"></script>
<script type="text/babel" data-type="module" data-presets="env,react">
const {useEffect, useState} = React;
// simulate making a network request to get a random number from an API:
// it will return a promise which will (at some point in the future)
// resolve with the random number, or reject with an Error
function mockFetchRandomNumber () {
const randomNumber = Math.floor(Math.random() * 1000) + 1; // 1-1000
const delay = Math.floor(Math.random() * 1000) + 1000; // 1-2s
const chance = 0.2; // percent chance of random network failure
return new Promise((resolve, reject) => setTimeout(() => {
if (chance > Math.random()) reject(new Error('Network error'));
else resolve(randomNumber);
}, delay));
}
// a custom hook to wrap the logic of fetching the random number
// and maintain the state of the request while doing so
function useRandomNumber () {
const [data, setData] = useState(); // the potential data
const [error, setError] = useState(); // a potential error
const [isLoading, setIsLoading] = useState(false); // whether the request is still pending
const [reloadBoolean, setReloadBoolean] = useState(false);
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
setData(undefined);
setError(undefined);
try {
const randomNumber = await mockFetchRandomNumber();
setData(randomNumber);
setError(undefined);
}
catch (ex) {
setError(ex instanceof Error ? ex : new Error(String(ex)));
setData(undefined);
}
setIsLoading(false);
};
fetchData();
}, [reloadBoolean, setData, setError, setIsLoading]);
return {
data,
error,
isLoading,
// will toggle the value of `reloadBoolean`, forcing a re-render
reload: () => setReloadBoolean(b => !b),
};
}
function Example () {
const {data, error, isLoading, reload} = useRandomNumber();
return (
<div>
{
isLoading
? (<div>Loading random number...</div>)
: null
}
{
error
? (<div>There was an error loading the data ({error.message})</div>)
: null
}
{
data
? (<div>The random number is: {data}</div>)
: null
}
<button onClick={reload}>Get new number</button>
</div>
);
}
ReactDOM.render(<Example />, document.getElementById('root'));
</script>
tl;博士
创建一个 Observable 以定期调用 API-端点:
import { distinctUntilChanged, switchMap, timer } form 'rxjs'; /* Use RxJS library for convenience */
const getRandomNumber = contract.connect(signer).randomResult();
const observable = timer(0, 1000) /* Trigger now and each 1000 ms */
.pipe(
switchMap(getRandomNumber), /* On each run, get the current number */
distinctUntilChanged(), /* Only trigger subscribers if new number */
)
const subscription = observable.subscribe((number) => console.log(number));
/* Don't forget to unsubscribe after, e.g. when the component unmounts */
subscription.unsubscribe();
长版
观察者模式允许您接收多个异步事件的通知(e.i。'subscribe')- 与 javascript Promise
在单个事件后通知您的方式相同异步事件完成。 (观察者实际上比这更灵活,这只是一个用例)
一个天真的javascript实现
让我们看看如何在基本 javascript
中实现您想要的行为
let currentRandomNumber = null;
let isCanceled = false;
async function checkAndUpdateNumber() {
while (!isCanceled) {
/* Set your new (or same) number */
currentRandomNumber = await contract.connect(signer).randomResult();
/* Wait 1000ms */
await new Promsie((resolve) => setTimeout(resolve, 1000));
}
}
checkAndUpdateNumber();
/* If you want to stop the loop */
isCancelled = true;
此实现有效,但仍有很大的改进空间。代码一点都不可重用,也不容易测试。
Observers 为您提供了一个更简洁的界面来处理多个异步操作。查看 this 文章以了解观察者如何在幕后工作。
Observables 的首选 javascript 库是 RxJS。它经过充分测试并提供了无数实用方法,因此我强烈建议您检查一下。
我正在使用 Chainlink Oracles 获取随机数。这个获取随机数的过程需要一段时间。为此,我必须执行这一行(异步调用),它调用我的智能合约的一个函数并存储新的随机数:
const newRandomNumber = await contract.connect(signer).randomResult();
我想要的是使这个过程自动化:当生成一个新号码(并且可以使用)时,我想向用户显示一条消息(在我的前面)。
Hey, a new number has been generated.
如何定期检查 newRandomNumber
中存储的结果是否已更改?当发生这种情况时,我如何显示消息?
因为您在问题上标记了 React,所以这里有一个使用 React 状态的注释示例:
<div id="root"></div><script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/standalone@7.16.6/babel.min.js"></script>
<script type="text/babel" data-type="module" data-presets="env,react">
const {useEffect, useState} = React;
// simulate making a network request to get a random number from an API:
// it will return a promise which will (at some point in the future)
// resolve with the random number, or reject with an Error
function mockFetchRandomNumber () {
const randomNumber = Math.floor(Math.random() * 1000) + 1; // 1-1000
const delay = Math.floor(Math.random() * 1000) + 1000; // 1-2s
const chance = 0.2; // percent chance of random network failure
return new Promise((resolve, reject) => setTimeout(() => {
if (chance > Math.random()) reject(new Error('Network error'));
else resolve(randomNumber);
}, delay));
}
// a custom hook to wrap the logic of fetching the random number
// and maintain the state of the request while doing so
function useRandomNumber () {
const [data, setData] = useState(); // the potential data
const [error, setError] = useState(); // a potential error
const [isLoading, setIsLoading] = useState(false); // whether the request is still pending
const [reloadBoolean, setReloadBoolean] = useState(false);
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
setData(undefined);
setError(undefined);
try {
const randomNumber = await mockFetchRandomNumber();
setData(randomNumber);
setError(undefined);
}
catch (ex) {
setError(ex instanceof Error ? ex : new Error(String(ex)));
setData(undefined);
}
setIsLoading(false);
};
fetchData();
}, [reloadBoolean, setData, setError, setIsLoading]);
return {
data,
error,
isLoading,
// will toggle the value of `reloadBoolean`, forcing a re-render
reload: () => setReloadBoolean(b => !b),
};
}
function Example () {
const {data, error, isLoading, reload} = useRandomNumber();
return (
<div>
{
isLoading
? (<div>Loading random number...</div>)
: null
}
{
error
? (<div>There was an error loading the data ({error.message})</div>)
: null
}
{
data
? (<div>The random number is: {data}</div>)
: null
}
<button onClick={reload}>Get new number</button>
</div>
);
}
ReactDOM.render(<Example />, document.getElementById('root'));
</script>
tl;博士
创建一个 Observable 以定期调用 API-端点:
import { distinctUntilChanged, switchMap, timer } form 'rxjs'; /* Use RxJS library for convenience */
const getRandomNumber = contract.connect(signer).randomResult();
const observable = timer(0, 1000) /* Trigger now and each 1000 ms */
.pipe(
switchMap(getRandomNumber), /* On each run, get the current number */
distinctUntilChanged(), /* Only trigger subscribers if new number */
)
const subscription = observable.subscribe((number) => console.log(number));
/* Don't forget to unsubscribe after, e.g. when the component unmounts */
subscription.unsubscribe();
长版
观察者模式允许您接收多个异步事件的通知(e.i。'subscribe')- 与 javascript Promise
在单个事件后通知您的方式相同异步事件完成。 (观察者实际上比这更灵活,这只是一个用例)
一个天真的javascript实现
让我们看看如何在基本 javascript
中实现您想要的行为let currentRandomNumber = null;
let isCanceled = false;
async function checkAndUpdateNumber() {
while (!isCanceled) {
/* Set your new (or same) number */
currentRandomNumber = await contract.connect(signer).randomResult();
/* Wait 1000ms */
await new Promsie((resolve) => setTimeout(resolve, 1000));
}
}
checkAndUpdateNumber();
/* If you want to stop the loop */
isCancelled = true;
此实现有效,但仍有很大的改进空间。代码一点都不可重用,也不容易测试。
Observers 为您提供了一个更简洁的界面来处理多个异步操作。查看 this 文章以了解观察者如何在幕后工作。
Observables 的首选 javascript 库是 RxJS。它经过充分测试并提供了无数实用方法,因此我强烈建议您检查一下。