在构建脚本中使用 util.promisfy 无法按预期工作

Posted

技术标签:

【中文标题】在构建脚本中使用 util.promisfy 无法按预期工作【英文标题】:Using util.promisfy in build script not working as expected 【发布时间】:2019-03-07 20:45:24 【问题描述】:

我在节点中有一个构建脚本,它在某一时刻重写了指向 ./dist 引用的链接中的所有 ./src 引用。我一直在阅读 util.promisfy 并尝试将 async/await 合并到我的脚本中,但它没有按计划工作。我可以将我的文件从 /src 移动到 /dist 目录并 uglify index.js 并压缩我的图像,但是使用节点 fs 函数来读取和写入我的 index.html 文件来更新链接是行不通的。下面是 build.js 的相关部分:

const fs = require("fs");
const fc = require("file-copy");
const  promisify  = require("util");
const copyFileAsync = promisify(fs.access); // convert fs.access to a promise
const readFileAsync = promisify(fs.readFile); // convert fs.readFile to a promise
const confirmWriteAsync = promisify(fs.stat); // convert fs.stat to a promise;
const writeFileAsync = promisify(fs.writeFile); // convert fs.writeFile to a promise

const mkdirp = require("mkdirp");
       // Compressed and uglified files here ok //

      // ============ Copy index.html to dist/index.html(copyIndexHtml) ============ //
      /* jshint ignore:start */
      const copyIndexFile = async function(result) 
    try 
      console.log(result);
      await copyFileAsync(
        "./index.html",
        fs.constants.R_OK | fs.constants.W_OK
      )
      await fc("./index.html", "./dist/index.html");
     catch (err) 
      console.log("ERROR:", err);
        
        return "Copied Index.html to /dist!";
      ; // end copyIndexFile
      /* jshint ignore:end */

      // ================== End copyIndexFile ================ //

      // ====== Read data from dist/index.html(getData) =============== //


      /* jshint ignore:start */
      const getData = async function(result) 
        console.log(result);

        // Lets update dist/index.html file src and href links to reflect new location. 
        console.log(
          "index.html: Redoing file links to reflect move to /dist folder."
        );
        try 
          const fileContents = await readFileAsync("./dist/index.html", 
            encoding: "utf8"
          );
          console.log("CONTENT:", fileContents);

          // check and replace both src= and href= links to reflect chenge to dist/ folder
          // Notice we chained .replace to do it
          const regEx1 = /src\s*=\s*"\.\/src\//gi;
          const regEx2 = /src\s*=\s*'\.\/src\//gi;
          const regEx3 = /href\s*=\s*"\.\/src\//gi;
          const regEx4 = /href\s*=\s*'\.\/src\//gi;

          let distIndexHtml = fileContents
            .replace(regEx1, 'src="./')
            .replace(regEx2, "src='./")
            .replace(regEx3, 'href="./')
            .replace(regEx4, "href='./");

          console.log(distIndexHtml);

          // Confirm Write to index.html
          await confirmWriteAsync("./dist/index.html", function(err, stats) 
            if (err) 
              console.log(`Error: $err`);
             else if (stats.size === 0) 
              console.log(`Error copying index.html!!!!!!`);
             else 
              console.log(
                `Succesfully copied to dist\index.html. File size is $
                  stats.size
                `
              );
            
          );

          await writeFileAsync(
            "dist/index.html",
            distIndexHtml,
            "utf8",
            err => 
              if (err) 
                reject(err);
               else 
                resolve("Write to dist//index.html OK.");
              
            
          );
         catch (err) 
          console.log("ERROR:", err);
        
        return "Read /dist/index.html file!!";
      ;
      /* jshint ignore:end */

      // ==================================================== //
      // ========== Call promise chain ====================== //
      // ==================================================== //
      browserifyJS()
        .then(
          result => 
            return compressImages(result);
          ,
          err => 
            console.log(err);
            return compressImages(err);
          
        )
        .then(result => 
          return copyIndexFile(result);
        )
        .then(result => 
          return getData(result);
        )
        .then(result => 
          console.log(result);
        );
     // mkdirp else end
  ); // mkdirp callback end
); // rimraf callback end

更正后更新控制台读数:控制台读数为:

    npm run build

> sports-page-app@1.0.0 build C:\Users\akillian\Local Documents\GitHub\sports-page-app
> node ./scripts/build

main.css: build and uglify
Checking for index.js
Bundling Successful!
Images Compressed!!!
/dist/index.js: build and uglify
Copied Index.html to /dist!
index.html: Redoing file links to reflect move to /dist folder.
CONTENT:

Succesfully copied to distindex.html. File size is 3059
~\Local Documents\GitHub\sports-page-app [refactor-app ≡ +0 ~1 -0 !]

CONTENT 现在是空白的。

【问题讨论】:

【参考方案1】:

你有这个:

      await copyFileAsync(
        "./index.html",
        fs.constants.R_OK | fs.constants.W_OK,
        err => 
          if (err) 
            console.log("No index.html file present!");
           else 
            // Note: fc() returns a promise and no .catch()
            // This also means the code continues on without
            // waiting for the file to copy.
            fc("./index.html", "./dist/index.html"); 
          
        
      );

但是如果你承诺它,就没有错误回调函数。 简单地说:

      await copyFileAsync(
        "./index.html",
        fs.constants.R_OK | fs.constants.W_OK
      )
      await fc("./index.html", "./dist/index.html");

你的 try/catch 会得到错误。

此外,即使出现错误,也始终返回特定的 try/catch return "Copied Index.html to /dist!";,因此我建议制作两个返回语句,一个在 try 内,一个在 catch 内,或者使用 finally如果没关系。

【讨论】:

非常感谢!做到了。所以当你承诺你否定任何 fs 方法的回调时? 我问是因为控制台读数显示更新的链接,但当我查看 ./dist/index.html 时没有显示?? 是的,你应该,一般来说。一些 fs 方法是“事件发射器”,我相信你不能使用 promisify。 Promisify 应该只用于节点样式的回调函数,.e.g. someFunction(foo,bar,function(err,data))

以上是关于在构建脚本中使用 util.promisfy 无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

无法从 Windows 批处理脚本构建 C 程序

Jenkins作业无法在构建期间将整数参数传递给python脚本

为啥尽管在图像构建期间通过 `composer global install` 安装了“drush”,但我无法从正在运行的 PHP 脚本中找到该工具?

Nextjs 无法在生产 node_env 的“.next”目录中找到有效的构建

Jenkins 无法捕获构建脚本错误问题

无法为 Vue Webpack 构建的应用程序加载 Worker 脚本