【问题标题】:What are ways to run a script only after another script has finished?只有在另一个脚本完成后才运行脚本的方法是什么?
【发布时间】:2020-08-16 10:18:30
【问题描述】:

假设这是我的代码(只是我写的一个示例来展示这个想法)

var extract = require("./postextract.js");
var rescore = require("./standardaddress.js");

RunFunc();

function RunFunc() {
    extract.Start();
    console.log("Extraction complete");
    rescore.Start();
    console.log("Scoring complete");
}

我不想让 rescore.Start() 运行,直到整个 extract.Start() 完成。两个脚本中都包含一个函数蜘蛛网,因此将回调直接放入 Start() 函数似乎不可行,因为最终函数不会返回它,而且我在理解如何使用 Promises 时遇到了很多麻烦.有什么方法可以完成这项工作?

这些是 extract.Start() 开始和结束的脚本。 OpenWriter() 是通过多个其他函数和流获得的,实际的 fileWrite.write() 位于附加到此的另一个脚本中(尽管不需要检测运行结束。目前,fileWrite.on('finish')是我希望脚本被确定为完成的地方

module.exports = {
  Start: function CodeFileRead() {
    //this.country = countryIn;
    //Read stream of thate address components
    fs.createReadStream("Reference\\" + postValid.country + " ADDRESS REF DATA.csv")
      //Change separator based on file
      .pipe(csv({escape: null, headers: false, separator: delim}))
      //Indicate start of reading
      .on('resume', (data) => console.log("Reading complete postal code file..."))
      //Processes lines of data into storage array for comparison
      .on('data', (data) => {
        postValid.addProper[data[1]] = JSON.stringify(Object.values(data)).replace(/"/g, '').split(',').join('*');
        })
      //End of reading file
      .on('end', () => {
        postValid.complete = true;
        console.log("Done reading");
        //Launch main script, delayed to here in order to not read ahead of this stream
        ThisFunc();
      });
  },

  extractDone
}

function OpenWriter() {
    //File stream for writing the processed chunks into a new file
    fileWrite = fs.createWriteStream("Processed\\" + fileName.split('.')[0] + "_processed." + fileName.split('.')[1]);
    fileWrite.on('open', () => console.log("File write is open"));
    fileWrite.on('finish', () => {
      console.log("File write is closed");
    });
}

编辑:我不想简单地将下一个脚本添加到前一个脚本的末尾并放弃主文件,因为我不知道它将持续多长时间并且它应该被设计为能够占用在我们的开发阶段之后的其他脚本。我不能只使用现有的包,因为公司的审批时间最多需要两周,我更需要这个

双重编辑:这是我所有的代码,每个脚本和函数都是我编写的,所以我可以让被调用的脚本做需要的事情

【问题讨论】:

  • extract.Start() 是否返回承诺?
  • 我将如何做到这一点?我写了它们,所以无论我想要它返回什么,我只是不确定在哪里或如何
  • 您必须为extract.Start()rescore.Start(); 发布一个简单的最小完整可验证代码示例
  • 添加到帖子中,它显示了第一个和最后一个脚本,两者功能相同(以读取流开始,以写入流结束)

标签: javascript node.js asynchronous promise callback


【解决方案1】:

没有通用的方法来确定函数调用所做的一切何时完成。

它可能接受回调。它可能会返回一个承诺。它可能不提供任何方法来确定何时完成。它可能有副作用,您可以通过轮询来监控。

您需要阅读该特定功能的文档和/或源代码。

【讨论】:

  • 它们是我的函数,我编写了整个代码,所以我可以让它们返回或执行所需的操作
  • @TheBasementNerd — 我们不知道他们在做什么。我建议了三件事,可用于确定异步代码何时在此答案中完成(尽管轮询副作用是糟糕)。选择其中一个并让函数执行此操作。
  • 除了回调之外,我不确定如何将这些放入其中,但是当它调用脚本中的一个函数并且脚本以另一个结束时,我没有通过每个函数传递回调不认为这是可行的。或者听起来可能必须这样?
【解决方案2】:

使用 async/await(承诺),例如:

var extract = require("./postextract.js");
var rescore = require("./standardaddress.js");
RunFunc();

async function extract_start() {
   try {
       extract.Start()
   }
   catch(e){
      console.log(e)
   }
}

async function rescore_start() {
   try {
       rescore.Start()
   }
   catch(e){
      console.log(e)
   }
}

async function RunFunc() {
    await extract_start();
    console.log("Extraction complete");
    await rescore_start();
    console.log("Scoring complete");
}

【讨论】:

  • 这最终只是运行 extract.Start() 然后程序结束,这似乎是大多数时候我尝试做一个承诺系统的问题,或者我需要把提取和重新评分脚本中的内容?
【解决方案3】:

你可以把你的函数包装在 Promise 中并返回它。

module.exports = {
  Start: function CodeFileRead() {
    return new Promise((resolve, reject) => {
      fs.createReadStream(
        'Reference\\' + postValid.country + ' ADDRESS REF DATA.csv'
      )
      // .......some code...
      .on('end', () => {
        postValid.complete = true;
        console.log('Done reading');
        resolve('success');
      });
    });
  }
};

然后像这样运行 RunFunc:

async function RunFunc() {
  await extract.Start();
  console.log("Extraction complete");
  await rescore.Start();
  console.log("Scoring complete");
}

//or IIFE
RunFunc().then(()=>{
  console.log("All Complete");
})

注意:当出现一些错误时,您也可以/应该通过reject("some error") 处理错误。

了解 TheFunc() 后编辑:

制作一个新的事件发射器可能是最简单的解决方案:
eventEmitter.js

const EventEmitter = require('events').EventEmitter
module.exports = new EventEmitter()
const eventEmitter = require('./eventEmitter');
module.exports = {
  Start: function CodeFileRead() {
    return new Promise((resolve, reject) => {
      //after all of your code
      eventEmitter.once('WORK_DONE', ()=>{
        resolve("Done");
      })
    });
  }
};
function OpenWriter() {
  ...
  fileWrite.on('finish', () => {
    console.log("File write is closed");
    eventEmitter.emit("WORK_DONE");
  });
}

然后像以前一样运行 RunFunc。

【讨论】:

  • 这最终会一起运行它们而不是等待整个脚本完成
  • 那么ThisFunc也是异步函数吗?我以为那是个假人。
  • 调用该脚本函数链中的下一个函数。该链最终以调用 OpenWriter 结束
  • 它不是异步的,它只是被使用,因为我们需要在开始处理所有数据的过程之前将整个文件加载到内存中
  • 这对我的家庭自动化系统也很有帮助,因为我需要一种方法来检测色调灯何时发生变化,所以使用事件发射器是神发送
猜你喜欢
  • 2020-05-18
  • 1970-01-01
  • 2012-01-09
  • 2011-11-21
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多