Using async await on custom promise

2019-02-25 05:51发布

问题:

Im trying to use async await on a function that returns a promise but the out put im getting is Promise { <pending> }. In here im using function called convertFiletoPDF which returns a promise. I need to get the output (the path that i have mention in resolve() ). When i use it as

convertFiletoPDF(file).then((result) => {
  console.log(result);
}).catch((err)=>{
  console.log(err);
});

it gives the expected result.Whats wrong with the code below? im quite new to these async await and promises.

 function convertFiletoPDF(file) {
  return new Promise(function(resolve, reject) {
    unoconv.convert(file, "pdf", function(
      err,
      result
    ) {
      if (err) {
        reject(err);
      }
      let File = file.substring(file.lastIndexOf("/")+1,file.lastIndexOf("."));
      // result is returned as a Buffer
      fs.writeFile(__dirname+"/files/converted/"+File+".pdf", result, error => {
        /* handle error */
        if (err) reject(error);
        else resolve("./files/converted/"+File+".pdf");
      });
    });
  });
}

async function myfunc(file){
  let res = await convertFiletoPDF(file);
  return res;
}

let res = myfunc(file);
console.log(res);

回答1:

The return value of an async function is a promise, so naturally that's what your console.log outputs. You need to either consume the result via await (within another async function) or use then/catch (within another async function).

This is what you're currently doing:

function convertFiletoPDF(file) {
  return new Promise(function(resolve, reject) {
    setTimeout(resolve, 400, "Done");
  });
}

async function myfunc(file){
  let res = await convertFiletoPDF(file);
  return res;
}

let res = myfunc("some file");
console.log(res);

You need to be doing either this:

function convertFiletoPDF(file) {
  return new Promise(function(resolve, reject) {
    setTimeout(resolve, 400, "Done");
  });
}

async function myfunc(file){
  let res = await convertFiletoPDF(file);
  return res;
}

(async() => {
  try {
    let res = await myfunc("some file");
    console.log(res);
  } catch (e) {
    // Deal with the fact there was an error
  }
})();

or with then and catch:

function convertFiletoPDF(file) {
  return new Promise(function(resolve, reject) {
    setTimeout(resolve, 400, "Done");
  });
}

async function myfunc(file){
  let res = await convertFiletoPDF(file);
  return res;
}

myfunc("some file")
  .then(res => {
    console.log(res);
  })
  .catch(e => {
    // Deal with the fact there was an error
  });



回答2:

convertFiletoPDF() 

This function run and returned a Promise. This is fine.

myfunc()

Lets say myfunc takes 10 seconds. Javascript starts to wait newly created thread result from libuv via event loop mechanism. So, Javascript says, "That one is async, I will not wait, when it finishes it will let me know and i will run my then callback and then I will proceed with its output."

Javascript keeps his promise. Tries to run next below lines. myFunch is still working. Output is not ready yet. Returns undefined.

let res = myfunc(file);
console.log(res);

You get undefined.



回答3:

Someone might find this example from my code useful. You can wrap it in a promise and then resolve the custom promise and then call another promise to confirm the receipt of the original web3 call.

return new Promise((resolve, reject) => {
    tokenContract.methods.approve(
        exchangeAddress, 
        BIG_NUMBER_1e50
    )
    .send({ from })
    .once('transactionHash')
    .once('receipt', receipt => resolve(receipt))
    .on('confirmation')
    .on('error', err => reject(err))
    .then( receipt => // will be fired once the receipt its mined
        console.log(receipt),
    );
});