Search code examples
javascriptnode.jskoa

Why if I put resolve() into the callback function of fs, the promise doesn't return


(tips: I'm using a nodejs framework eggjs based on koa)

The code below can run successfully.But if I put resolve() into callback function of fs.renameSync(), the promise won't return any thing, and the request keeps pending status.

What causes this? Does this have to do with the order of execution?


 async uploadAsset(assetName, file) {
    const { app } = this;
    const logger = this.logger;
    return new Promise(function(resolve, reject) {
      fs.renameSync(file.filepath, `${app.config.multipart.projectAssetLocalPath}${assetName}`, err => {
        if (err) {
          logger.warn(err);
          reject();
        }
      });
      resolve();
    });
  }

Solution

  • renameSync is a synchronous version of rename. It does not accept a callback as an argument; it only accepts an oldpath and a newpath. If you pass a third argument, it will be ignored; the callback function you're passing is never called.

    If you want this to be callback-based, use fs.rename instead, which does take a callback.

    Your resolve is also outside the callback at the moment, when it should be inside:

    async uploadAsset(assetName, file) {
      const { app } = this;
      const logger = this.logger;
      return new Promise(function(resolve, reject) {
        fs.rename(file.filepath, `${app.config.multipart.projectAssetLocalPath}${assetName}`, err => {
          if (err) {
            logger.warn(err);
            reject();
          }
          resolve();
        });
      });
    }
    

    Or use fs.promises instead, to accomplish this without constructing the Promise yourself.

    async uploadAsset(assetName, file) {
      const { app } = this;
      const logger = this.logger;
      return fs.promises.rename(file.filepath, `${app.config.multipart.projectAssetLocalPath}${assetName}`)
        .catch((err) => {
          logger.warn(err);
          throw new Error(err);
        });
    }