javascript - 导出异步等待变量并在 JS 中完成 "awaiting"后将其导入另一个文件

标签 javascript node.js asynchronous async-await

我刚开始用 JS 编写代码来为我的脚本创建一个网站,但我遇到了一些菜鸟问题。

我正在通过连接到获取函数的异步等待函数更新变量。我想在另一个脚本中呈现我的变量,这样做让我头疼不已。

这是我目前所拥有的,但似乎第二个文件正在导入 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 可以做到这一点,但它不是一个客户端友好的界面)。

相反,我建议导出一个函数,可以是直接checkStats,也可以是进行索引的包装器,以便为消费者整齐地准备数据,返回打包到对象中的数据。

您的意图似乎是只获取一次数据。如果您担心该函数会在每次重新渲染时继续访问 API,一旦 promise 已解决,进一步调用 await promise 只会返回旧值而不是重新计算它。在下面的示例代码中,我只使用一个 promise 并将其存储在一个变量中,因此无论 getStats 被调用了多少次,fetch 都只被调用一次。

您的导入器应在等待 promise 解析时提供默认值(通常您可以将它们导出为单独的同步变量,但为什么数据获取模块要关心 UI/ View 问题?我会将其保留在导入器中)。

最后,看起来您正在使用 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>

关于javascript - 导出异步等待变量并在 JS 中完成 "awaiting"后将其导入另一个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66147512/

相关文章:

java - 顶点抛出 IllegalStateException : Response has already been written

c# AsyncSocket 服务器需要锁定?

c# - 如何从 ffmpeg 异步流式输出

c# - 获取父页面名称

页面显示时的Javascript事件?

javascript - 如何根据当前日期从数组中找到最接近的日期值?

node.js - 如何使用 GraphQL 的数组模式类型

javascript - JQuery 如何在使用 Moment JS 时返回正确的日期

node.js - Mu2 对比 Mustache.js?我应该使用 Mu2 模块还是 Mustache.js 模块进行 nodejs 模板化

javascript - 使用promise.all在node js中进行外部api调用