在自定义承诺上使用异步等待

Posted

技术标签:

【中文标题】在自定义承诺上使用异步等待【英文标题】:Using async await on custom promise 【发布时间】:2018-03-14 23:45:47 【问题描述】:

我试图在一个返回承诺的函数上使用异步等待,但我得到的输出是 Promise <pending> 。在这里,我使用了一个名为 convertFiletoPDF 的函数,它返回一个承诺。我需要得到输出(我在 resolve() 中提到的路径)。 当我使用它时

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

它给出了预期的结果。下面的代码有什么问题?我对这些异步等待和承诺很陌生。

 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】:

async 函数的返回值是一个承诺,所以很自然这就是你的console.log 输出的值。您需要通过await(在另一个async 函数内)或使用then/catch(在另一个async 函数内)使用结果。

这是你目前正在做的事情:

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);

您需要这样做:

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
  
)();

或使用thencatch

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() 

这个函数运行并返回一个 Promise。这很好。

myfunc()

假设myfunc 需要 10 秒。 javascript 开始通过event loop 机制等待来自libuv 的新创建线程结果。所以,Javascript 说,“那是异步的,我不会等待,当它完成时它会通知我,我将运行我的 then 回调,然后我将继续它的输出。”

Javascript 信守诺言。尝试在下一行运行。 myFunch 仍在工作。输出还没有准备好。返回未定义。

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

你没有定义。

【讨论】:

【参考方案3】:

有人可能会从我的代码中发现这个示例很有用。您可以将其包装在一个 Promise 中,然后解析自定义 Promise,然后调用另一个 Promise 以确认收到原始 web3 调用。

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),
    );
);

【讨论】:

以上是关于在自定义承诺上使用异步等待的主要内容,如果未能解决你的问题,请参考以下文章

带有请求承诺的异步/等待返回未定义

等待组件在自定义 svelte 指令中准备就绪

异步等待承诺上的 UnhandledPromiseRejectionWarning

无法使用 Terraform 在自定义 VPC 中创建 Elastic Beanstalk 应用程序

如何在自定义组件宿主元素上使用自定义指令

Gatsby:在自定义帖子类型上使用 GraphQL 查询和自定义分类