【问题标题】:chaining promises in functions在函数中链接承诺
【发布时间】:2021-05-03 09:44:21
【问题描述】:

我有一个小问题,如何以合理的方式创建一个promise链,让makeZip函数首先添加所有必要的文件,然后创建zip,最后删除之前添加的文件? (makeZip 函数也必须返回一个承诺)。在下面的示例中,我没有在任何地方调用 deleteFile,因为我不知道在哪里调用它。当我尝试在添加文件函数中调用它以在添加文件后立即删除文件时,由于某种未知原因,控制台显示了制作的 zip!先登录再删除文件。

const deleteFile = (file, result) => {
  new Promise((resolve, reject) => {
    fs.unlink(`./screenshots/${file}`, (err) => {
      if (err) return reject(err);
      console.log(`${file} deleted!`);
      return resolve();
    });
  });
};

const addFile = (file) => {
  new Promise((resolve, reject) => {
    try {
      zip.addLocalFile(`./screenshots/${file}`);
      console.log(`${file} added`);
      return resolve();
    } catch {
      return reject(new Error("failed to add file"));
    }
  });
};

const makeZip = () => {
  Promise.all(fs.readdirSync("./screenshots").map((file) => addFile(file)))
    .then(() => {
      return new Promise((resolve, reject) => {
        try {
          zip.writeZip(`./zip_files/supername.zip`);
          console.log("zip maked!");
          resolve();
        } catch {
          return reject(new Error("failed making zip"));
        }
      });
    })
    .catch((err) => console.log(err));
};

【问题讨论】:

  • 我认为你的程序无效,为什么addFile()返回promise对象? zip.addLocalFile()zip.writeZip() 是异步的吗?如果是这样,您是否在zip.addLocalFile()zip.writeZip() 之前忘记了await
  • zip.addLocalFilezip.writeZip 实际上是异步的吗?如果是,您 promisified them wrong(在通话后立即解决,而不是在他们完成时解决 - 他们应该接受回调?),如果不是,您根本不需要将它们包装在 new Promise 中。
  • 即使他 (@Vasper) 也忘记从每个函数返回承诺

标签: javascript node.js ecmascript-6


【解决方案1】:

主要原因是您没有返回您在函数调用中实例化的承诺。另外我有一些很酷的建议可以提高你的代码清洁度。

[TIP]:曾经检查过NodeJSutil包中的promisify函数,它带有node,非常方便将需要回调作为参数的函数转换为promise返回函数。,我将在下面演示无论如何。

// so I will work with one function because the problem resonates with the rest, so
// let us look at the add file function.

// so let us get the promisify function first
const promisify = require('util').promisify;

const addFile = (file) => {
  // if addLocalFile is async then you can just return it
  return zip.addLocalFile(`./screenshots/${file}`);
};

// okay so here is the promisify example, realized it wasn't applicable int the function
// above
const deleteFile = (file, result) => {
  // so we will return here a. So because the function fs.unlink, takes a second arg that
  // is a callback we can use promisify to convert the function into a promise
  // returning function.
  return promisify(fs.unlink)(`./screenshots/${file}`);
  // so from there you can do your error handling.
};

所以现在让我们把它们放在你的最后一个函数中,即makeZip

const makeZip = () => {
  // good call on this, very interesting.
  Promise.all(fs.readdirSync("./screenshots").map((file) => addFile(file)))
    .then(() => {
      return zip.writeZip(`./zip_files/supername.zip`);
    })
    .then(() => {
      //... in here you can then unlink your files.
    });
    .catch((err) => console.log(err));
};

有了这些建议,一切都会好起来的,希望它能奏效......

【讨论】:

  • 我只会向unlink 承诺一次 - const unlink = promisify(fs.unlink);
【解决方案2】:

谢谢大家的指点,原来解决方案要简单得多,只需使用 fs.unlinkSync 方法而不是异步 fs.unlink。

const deleteFile = (file) => {
  try {
    fs.unlinkSync(`./screenshots/${file}`);
    console.log(`${file} removed`);
  } catch (err) {
    console.error(err);
  }
};

const addFile = (file) => {
  try {
    zip.addLocalFile(`./screenshots/${file}`);
    console.log(`${file} added`);
    deleteFile(file);
  } catch (err) {
    console.error(err);
  }
};

const makeZip = () => {
  fs.readdirSync("./screenshots").map((file) => addFile(file));
  zip.writeZip(`./zip_files/supername.zip`);
  console.log("zip maked!");
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-06
    • 2014-10-30
    • 2017-08-12
    • 2017-03-27
    • 2017-02-05
    相关资源
    最近更新 更多