[英]Export an async await variable and import it to another file once its done “awaiting” in JS
我刚开始用 JS 编码为我的脚本制作一个网站,但我遇到了一些菜鸟问题。
我正在通过连接到获取 function 的异步等待 function 更新变量。 我想在另一个脚本中渲染我的变量,这样做会让人头疼。
这是我到目前为止所拥有的,但似乎第二个文件正在导入 nul 变量。
这是我的计算和变量声明文件:
var url = 'https://financialmodelingprep.com/api/v3/profile/'+tickersymb+'?apikey='+api
var priceStat = "Working..."
var jsonData
function checkStats(url, callback) {
return fetch(url)
.then((response) => {
return response.json().then((data) => {
console.log(data);
return data;
}).catch((err) => {
console.log(err);
})
});
}
(async () => {
jsonData = await checkStats(url)
priceStat = jsonData.[0].price
exports.jsonData = jsonData
exports.priceStat = priceStat
exports.tickersymb = tickersymb
})();
这是我的渲染脚本:
var compute = require('components/compute-engine');
var pricestat = compute.pricestat;
var tickersymb = compute.tickersymb;
var jsonData = compute.jsonData;
export default function HeaderStats() {
return (
<>
{/* Header */}
<div className="relative bg-blue-600 md:pt-32 pb-32 pt-12">
<div className="px-4 md:px-10 mx-auto w-full">
<div>
{/* Card stats */}
<div className="flex flex-wrap">
<div className="w-full lg:w-6/12 xl:w-3/12 px-4">
<CardStats
statSubtitle=""
ticker= {tickersymb}
exchange="NASDAQ"
statIconName="fas fa-dollar-sign"
statIconColor="bg-green-500"
/>
...
没有办法像这样将异步代码转换为同步代码,无论是跨模块还是在文件内。 一旦进入异步链,就永远无法将控制权重新交给同步代码,因为所有同步调用堆栈帧都需要在异步函数有机会解决之前完成。
因此,您需要导出 promise,然后在导入程序代码中await
它。
您可以应用一些模式,如果没有看到更大的设计上下文,我不确定哪种模式最好,但我不会尝试对这些单独的变量中的每一个使用 promise - 如果你没有任何意义想要一起使用它们( Promise.all
可以做到这一点,但它不是一个客户端友好的界面)。
相反,我建议直接导出 function,或者直接导出checkStats
,或者执行索引以整齐地为消费者准备数据的包装器,返回打包到 object 中的数据。
看来您的意图是只获取一次数据。 If you're worried that the function will keep hitting the API on every rerender, once a promise has resolved, further calls to await
the promise just return the old value instead of re-computing it. 在下面的示例代码中,我只使用了一个 promise 并将其存储在一个变量中,因此无论调用多少次getStats
都只调用一次fetch
。
您的导入器应在等待 promise 解析时提供默认值(您通常可以将这些导出为单独的同步变量,但为什么数据获取模块应该关心 UI/视图问题?我会将其保留在导入器中)。
最后,看起来您正在使用 React,因此组件需要以某种效果使用这些数据,而不是在组件外部的同步代码中。 如果您只想获取一次数据,请使用[]
作为useEffect
的第二个参数或将数据缓存在闭包中。
这是一个玩具示例来说明:
<script type="text/babel" defer> /**** mocks ****/ const fetch = async () => { console.log("fetch call made"); return { json: () => new Promise(resolve => setTimeout(() => resolve([{price: 42}]), 1000) ) }; }; const exports = {}; const require = () => exports; /**** exporter file ****/ const url = "https://www.example.com"; const checkStats = url => fetch(url).then(response => response.json()).catch(err => console.error(err)); // cache the promise const stats = checkStats(url).then(jsonData => ({price: jsonData[0].price})); exports.getStats = () => stats; /**** importer file ****/ const {useState, useEffect} = React; const {getStats} = require("./your-other-module"); const HeaderStats = () => { const [price, setPrice] = useState("loading..."); useEffect(() => { getStats().then(data => setPrice(data.price)); }, [price]); return (<h1>{price}</h1>); }; // show that even with 2 renders, fetch is // only called once (open browser console) ReactDOM.render( [<HeaderStats />, <HeaderStats />], document.body ); </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.