简体   繁体   中英

Wait for one function to finish before continuing?

When running the following code tidied in functions or not, it still writes to my file incorrectly. One thing that did work was wrapping those functions inside of a setTimeout method, with the seconds somewhere around 10. I just didn't like the idea of hardcoding those values and taking anymore time to complete than it should. What's a better way of going about this? I need help understanding async/await a little more as you can tell but what better way than to fail and ask for help!

  genPriceChangeScripts: async () => {
    const priceScript = `...`;

    const changeData = await get24hrChange();

    const globalCmds = [];
    const globalPol = [];

    const filtered = changeData.filter(function (item) {
      return (
        !item.symbol.includes("BTCUSDT_") && !item.symbol.includes("ETHUSDT_")
      );
    });

    async function scripts() {
      filtered.forEach((e) => {
        const data = e.symbol;

        const change = priceScript.replace("CHANGE", data);

        fs.writeFile(
          `../scripts/price_change/${data.toLowerCase()}_price_change.sh`,
          change,
          function (err) {
            if (err) return console.log(err);
          }
        );
      });
      console.log("scripts finished");
    }
    scripts();

    async function commands() {
      for (let i = 0; i < filtered.length; i++) {
        var pushCmds = `"#($CURRENT_DIR/scripts/price_change/${filtered[
          i
        ].symbol.toLowerCase()}_price_change.sh)"`;
        globalCmds.push(pushCmds);
      }

      const commands = globalCmds.join("\n");

      const cmdsWithComment = commands.concat("\n#CHANGE3");

      fs.readFile("../binance.tmux", "utf-8", (err, data) => {
        if (err) {
          throw err;
        }

        const addCmds = data.replace("#CHANGE1", cmdsWithComment);

        fs.writeFile("../binance.tmux", addCmds, (err) => {
          if (err) {
            throw err;
          }
        });
      });
      console.log("cmds finished");
    }
    commands();

    async function pols() {
      for (let i = 0; i < filtered.length; i++) {
        const pushPol = `"\\#{${filtered[
          i
        ].symbol.toLowerCase()}_price_change}"`;
        globalPol.push(pushPol);
      }

      const pol = globalPol.join("\n");

      const polWithComment = pol.concat("\n#CHANGE4");

      fs.readFile("../binance.tmux", "utf-8", (err, data) => {
        if (err) {
          throw err;
        }

        const addPol = data.replace("#CHANGE2", polWithComment);

        fs.writeFile("../binance.tmux", addPol, (err) => {
          if (err) {
            throw err;
          }
        });
      });
      console.log("pols finished");
    }
    pols();

    return prompt.end();
  },

The issue is that making a function async doesn't make it automatically wait for anything asynchronous going on inside it

async / await is syntax "sugar" for working with Promises, and Promises only

So, if you use the promise version of writeFile/readFile like so

import * as fs from 'fs/promise';

you can write your code as follows

genPriceChangeScripts: async() => {
    const priceScript = `...`;

    const changeData = await get24hrChange();

    const globalCmds = [];
    const globalPol = [];

    const filtered = changeData.filter(function (item) {
        return (!item.symbol.includes("BTCUSDT_") && !item.symbol.includes("ETHUSDT_"));
    });

    async function scripts() {
        const promises = filtered.map((e) => {
            const data = e.symbol;

            const change = priceScript.replace("CHANGE", data);

            return fs.writeFile(`../scripts/price_change/${data.toLowerCase()}_price_change.sh`, change);
        });
        await Promise.all(promises);
        console.log("scripts finished");
    }
    await scripts();

    async function commands() {
        for (let i = 0; i < filtered.length; i++) {
            var pushCmds = `"#($CURRENT_DIR/scripts/price_change/${filtered[i].symbol.toLowerCase()}_price_change.sh)"`;
            globalCmds.push(pushCmds);
        }

        const commands = globalCmds.join("\n");

        const cmdsWithComment = commands.concat("\n#CHANGE3");

        const data = await fs.readFile("../binance.tmux", "utf-8");
        const addCmds = data.replace("#CHANGE1", cmdsWithComment);
        await fs.writeFile("../binance.tmux", addCmds);
        console.log("cmds finished");
    }
    await commands();

    async function pols() {
        for (let i = 0; i < filtered.length; i++) {
            const pushPol = `"\\#{${filtered[i].symbol.toLowerCase()}_price_change}"`;
            globalPol.push(pushPol);
        }
        const pol = globalPol.join("\n");
        const polWithComment = pol.concat("\n#CHANGE4");
        const data = await fs.readFile("../binance.tmux", "utf-8");
        const addPol = data.replace("#CHANGE2", polWithComment);
        await fs.writeFile("../binance.tmux", addPol);
        console.log("pols finished");
    }
    await pols();

    return prompt.end();
},

You need to await the File System operations in order to wait for the asynchronous functions to return a response before proceeding.

await fs.readFile and await fs.writeFile

See this question for further explanation and examples.

This is in addition to adding await to your other async functions to propagate the promise chain correctly.

Not that I'm saying all your code works, but here are the kind changes I would make to get you in the correct direction:

// code above
  function scripts(){
    const a = [];
    filtered.forEach(e=>{
      const data = e.symbol, change = priceScript.replace('CHANGE', data);
      a.push(new Promise((resolve, reject)=>{
        fs.writeFile(`../scripts/price_change/${data.toLowerCase()}_price_change.sh`,
          change,
          err=>{
            if(err){
              reject(err);
            }
            else{
              resolve();
            }
          }
        );
      }));
    });
    return Promise.all(a);
  }
  await scripts();
// code below

Well... actually I would define the function somewhere else or not use it at all, but I think this is what you need to see.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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