【问题标题】:Setting Timeout to fs.copy function将超时设置为 fs.copy 函数
【发布时间】:2020-07-23 11:15:24
【问题描述】:
      global.resultArr = {};
      global.failedArr = [];
      global.successArr = [];    
       const writeFile = async function (dirResult, queryResult) {
  for (i = 0; i < queryResult.recordset.length; i++) {
    for (file of dirResult) {
      if (
        file.substring(file.length - 3) == "wav" &&
        global.failedArr.indexOf(queryResult.recordset[i].ip_vch) == -1
      ) {
        try {
          const writeResult = await timeout(
            fs.copy(
              dir + "//" + file,
              "//" +
                queryResult.recordset[i].ip_vch +
                "//RXWaveFiles//DynamicLibraries" +
                "//" +
                libid +
                "//" +
                file
            ),
            5000
          );
          if (
            writeResult &&
            global.failedArr.indexOf(queryResult.recordset[i].ip_vch) == -1
          ) {
            console.log(queryResult.recordset[i].ip_vch);
            global.failedArr.push(queryResult.recordset[i].ip_vch);
            await sql.query`update opower..dialers set fileMoveResult_int=0 where ip_vch =${queryResult.recordset[i].ip_vch}`;
          } else if (
            global.successArr.indexOf(queryResult.recordset[i].ip_vch) == -1 &&
            global.failedArr.indexOf(queryResult.recordset[i].ip_vch) == -1
          ) {
            global.successArr.push(queryResult.recordset[i].ip_vch);
            await sql.query`update opower..dialers set fileMoveResult_int=1 where ip_vch =${queryResult.recordset[i].ip_vch}`;
            console.log("success!" + queryResult.recordset[i].ip_vch);
          }
        } catch (error) {
          console.error(error);
          if (global.failedArr.indexOf(queryResult.recordset[i].ip_vch) == -1) {
            global.failedArr.push(queryResult.recordset[i].ip_vch);
            await sql.query`update opower..dialers set fileMoveResult_int=0 where ip_vch =${queryResult.recordset[i].ip_vch}`;
          }
        }
      }
    }
  }
  global.resultArr.success = successArr;
  global.resultArr.failed = failedArr;
  return global.resultArr;
};

    // utility function that creates a promise that rejects after a certain time
    function timeoutPromise(t, errMsg = "timeout") {
        // create possible error object here to get appropriate stack trace
        let e = new Error(errMsg);
        e.timeout = true;
        return new Promise((resolve, reject) => {
            setTimeout(reject, t, e);
        });
    }

// wrap a promise with a timeout, pass promise, time in ms and 
// optional timeout error message
function timeout(p, t, errMsg = "timeout") {
    return Promise.race(p, timeoutPromise(t, errMsg));
}

我在 for 循环中使用此 await 函数,在该循环中,我需要从源目录将一些文件复制到多个网络目录,但是 await 的问题是,对于失败的目录,它需要将近一分钟解决,然后将控制权交还给下一次迭代,有没有办法可以在 5 秒后停止当前迭代。

【问题讨论】:

  • 这里的目标是什么?如果它们花费超过 5 秒,您不想中止单个 fs.copy() 或所有 fs.copy() 操作吗?请向我们展示您在循环中的实际代码以及您要完成的工作(为您希望它的行为编写一个迷你规范)。听起来很奇怪,如果复制一个目录需要超过 5 秒,你就会中止它。
  • 这是我从数据库中获取不同目录的代码块,然后在所有这些目录中我需要复制一些文件并更新结果作为文件是否被复制,但是catch 是针对它无法复制的目录,我很晚才得到响应,由于控制仍然在循环中,我需要在一定时间后中断 for 循环迭代
  • 什么是fs.copy(),它来自哪里? fs 模块有 fs.copyFile()fs.promises.copyFile(),而不是 fs.copy()
  • 那么,如果你是 fs.copy() 花费的时间超过 5 秒,你想做什么?中止整个循环?
  • const fs = require('fs-extra')

标签: javascript node.js file async-await timeout


【解决方案1】:

您可以像这样为任何 Promise 添加错误超时:

// utility function that creates a promise that rejects after a certain time
function timeoutPromise(t, errMsg = "timeout") {
    // create possible error object here to get appropriate stack trace
    let e = new Error(errMsg);
    e.timeout = true;
    return new Promise((resolve, reject) => {
        setTimeout(reject, t, e);
    });
}

// wrap a promise with a timeout, pass promise, time in ms and 
// optional timeout error message
function timeout(p, t, errMsg = "timeout") {
    return Promise.race([p, timeoutPromise(t, errMsg)]);
}

你可以像这样使用fs.copy()

const writeResult = await timeout(fs.copy(...), 5000);

因此,如果 fs.copy() 花费的时间超过 5 秒,您正在等待的承诺将被拒绝,您可以在 catch 处理程序中捕获它并采取相应措施。您将能够看到错误对象具有.timeout 属性。

其工作方式是timeout() 函数在您传入的promise 和另一个在您的超时到期后将拒绝的promise 之间创建竞争。第一个完成控制Promise.race() 的输出,从而控制您使用await 的内容。如果超时获胜,则 Promise 将被拒绝。

【讨论】:

  • 我在 try 块中添加了这两个函数,现在每个目录的复制函数都失败了,错误是 is not iterable
  • @DeepanshuWadhwa - 首先,您不要将这两个函数放在现有函数中。将它们放在您可以访问的某个共享位置。然后,为了让我进一步提供帮助,您必须向我展示您尝试过的实际代码。您可以将其添加到问题的末尾(不要替换您拥有的内容,将其添加到末尾)并在您修改问题后向我发表评论。
  • @DeepanshuWadhwa - 我修复了代码中的错误。传递给Promise.race() 的两个承诺必须在一个数组中。这将解释您收到的错误消息。
  • 有什么方法可以使请求异步并且仍然能够正确更新数据库中的结果,我正在尝试 promise.all 请求,但它在控制台上显示我待处理的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-14
  • 1970-01-01
  • 2011-12-06
  • 2017-04-26
相关资源
最近更新 更多