【问题标题】:How make promise execute synchronously?如何让 promise 同步执行?
【发布时间】:2021-11-11 20:05:32
【问题描述】:

我使用 dom-to-image.js 将 dom 转换为 png 图像。由于 dom-to-image.js 使用 Promise,因此代码异步执行。我想同步执行 .then 函数。

我有以下代码:

domtoimage.toPng(document.getElementById("main")).then(function(dataUrl) {
    console.log(dataUrl);
}).catch(function(error) {
    console.error('oops, something went wrong!', error);
});

console.log("this console should be executed after console.log(dataUrl)")

我想先执行.then函数,然后再执行console.log("this console should be executed after console.log(dataUrl)")

请告诉我一些实现这一目标的方法。

【问题讨论】:

  • 为什么不放在then里面呢?还是做链接?
  • 这看起来像an XY problem。相信我,您想要同步执行 Promise,因为 1. 这是不可能的,并且 2. 它会阻碍性能。您实际上想在这里实现什么?
  • @PatrickRoberts 有有效的用例。如果你有一个遗留的、同步的代码库与一个异步的集成,你可能希望同步的东西异步和异步的东西同步到原型。

标签: javascript promise es6-promise


【解决方案1】:

当然有正当理由强制在 js 中同步执行一个 Promise。最明显的是当require'ing 需要使用一些异步的东西进行初始化的文件时,优化不是最重要的问题。

似乎synchronized-promise 包似乎应该可以解决问题。在你的情况下(警告 - 未经测试..):

const dti = () => docstoimage.toPng(document.getElementById("main"))
  .then(dataUrl => console.log('url: ', dataUrl))
  .catch(err => console.error('oops: ', err))

const sp = require('synchronized-promise')
const syncDti = sp(dti)
syncDti() // performs the 'synchronized version'

console.log("this console should be executed afterwards")

【讨论】:

  • synchronized-promise 依赖于另一个包 deasync,它修改了 Node.js 事件循环实现,以便同步执行所有代码,直到将 Promise 解析入队并处理。这在浏览器中不起作用。
  • 太棒了!与github.com/danday74/envsub 库一起使用。
  • 这会从同步函数中旋转事件循环。这似乎是一个非常糟糕的主意,因为它可能允许随机的其他事件循环任务在您的函数中间运行。
【解决方案2】:

试试这个:

async function doStuff(arg) {console.log(arg + "Assume this is a useful async function")}


doStuff.apply(/* What to specify as this */ this, /* List of args */ ["hello world "])

【讨论】:

    【解决方案3】:

    对于那些现在遇到这个问题的人:

    如果您不关心 IE 支持,您可以使用 async and await 来执行承诺,就好像它是同步的一样。 await 语法将暂停函数的执行,直到 Promise 解决,让您编写代码时就好像没有 Promise 一样。要捕获错误,请将其包装在 try/catch 块中。

    唯一需要注意的是,使用 await 语法要求您将其包装在使用 async 声明的函数中。

    async function toPng() {
      try {
        let dataUrl = await domtoimage.toPng(document.getElementById("main"));
        console.log(dataUrl);
      }
      catch (error ) {
        console.error('oops, something went wrong!', error);
      }
    
      console.log("this console should be executed after console.log(dataUrl)")
    }
    

    【讨论】:

    • 异步等待不会暂停函数执行,它确实返回了一个承诺。使用 then\catch 对 svii 来说只是语法糖
    • 这只是语法糖,不会真正改变执行的性质
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 2021-01-02
    • 1970-01-01
    • 2018-06-26
    • 2016-02-13
    相关资源
    最近更新 更多