繁体   English   中英

导出异步等待变量并在 JS 中完成“等待”后将其导入另一个文件

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM