【问题标题】:Is synchronous code in a Promise blocking? [closed]Promise 中的同步代码是否阻塞? [关闭]
【发布时间】:2019-04-17 22:45:22
【问题描述】:
function getPropsPromise(prop) {
    return new Promise(resolve => {
        resolve(prop());
    });
}

如果我在上面的“promisifying”函数中封装了一个同步方法:

function docProps() {
    const data = {};
    data['doc.title'] = document.title;
    return data;
}

像这样:

getPropsPromise(docProps)

这是否构成对 Promise 的错误应用?本质上,将 Promises 用于任何与网络无关的事情是否可以接受?如果是这样,那么直接从“docProps”函数返回一个 Promise 会更好,还是“承诺”它的调用服务于相同的目标?:

function docProps() {
    const data = {};
    data['doc.title'] = document.title;
    return new Promise(resolve => { resolve(data) };
}

【问题讨论】:

  • 当然,为什么不呢,你可以用 return Promise.resolve( data ) 做,或者让 docProps async 隐含地让它返回一个承诺......承诺中的长期运行方法仍然阻塞,看到 javascript 是单线程的,如果真的需要,那么你可以使用 webworker
  • Promises 的应用绝对没有错误,已经有一些库这样做了(例如bluebird。我不认为你的任何一个例子更好,只是不同,在第一种情况下你有通用函数,可以承诺任何其他函数并且可以重用,在第二个它只是函数返回承诺
  • 如果您使用Promise,则意味着您正在尝试解决问题,而Promise 是这样做的工具。通过Promise 解决的问题是避免阻塞主线程直到I/O 操作完成。在我们的浏览器中,网络和文件读取是依赖于网络或硬盘驱动器的任务,并且比计算任务慢得多 - 因此,它们会导致浏览器挂起直到完成。除非您有两个以不同速度移动的 "pieces",否则使用 Promise 并不能真正解决任何问题,也不会破坏任何东西。您的示例不需要承诺。

标签: javascript


【解决方案1】:

这是否构成对 Promise 的错误应用?本质上,将 Promises 用于任何与网络无关的事情是否可以接受?

不,可以将 Promise 用于非网络任务。它也用于读取文件、超时、异步处理、异步流等。

如果是这样,那么直接从'docProps'函数返回一个Promise会更好,还是'promisifying'它的调用服务于相同的目标?:

它们是等价的,但是如果docProps 返回了一个承诺并且你也将它包装在一个getPropsPromise promisif-ier 中,那将是多余的。此外,您的 getPropsPromise 可以替换为标准的 Promise.prototype.resolve 方法。即,

function getPropsPromise(prop) {
    return new Promise(resolve => {
        resolve(prop());
    });
}

getPropsPromise(func);

等价于

Promise.resolve(func());

最后,除非您的 docProps 是您为此问题创建的虚拟/占位符,否则它没有任何异步。您提供的 sn-ps 中似乎根本不需要 promise。

【讨论】:

  • 你的最后一点可能是最重要的。 OPs 代码根本没有做任何异步操作
  • 你明白了。我一直试图以一种不失礼貌的方式将您的最后一点传达给我的经理,但似乎无法真正指出从 DOM 中提取现有数据不是线程阻塞。他的主要例子是检索第一方 cookie 可能需要一些时间,因此它应该在一个承诺中。并不是说我们会立即散布上述数据。正如你所说,不需要 docProps 之类的承诺,但出于技术原因,为什么不呢?
  • JS 不是多线程的,并且 Promise 没有性能优势(事实上,由于开销导致了一些性能损失)。 Promise 旨在解决回调的语法/可读性问题,而不是提高性能。话虽如此,如果同步函数很慢但不是必需的,而不是承诺它,您可以考虑确保在其他更重要的函数完成后调用它。
  • 加一个Promise.resolve(func());
【解决方案2】:

如果docProps 是一个常规的同步函数,那么这样做只会让你的程序变慢。 Promise 中的同步代码仍将与所有其他代码在同一线程上运行,因此它仍会阻塞。

如果docProps 是异步的,那么它要么返回一个promise,要么接受一个回调。如果它返回一个 Promise,则将其包装在另一个 Promise 中是一种反模式。如果需要回调,则更正模式是在回调中调用 resolve,如下所示:

function getPropsPromise(prop) {
  return new Promise(resolve => {
      prop(() => {
        /* do stuff */
        resolve(/*something*/)
      });
  });
}

因此,无论哪种方式,都很难看到发布的代码有一个好的用例,除非你有一些期望得到承诺的东西并且你只有一个同步函数。在这种情况下,您可能最好使用Promise.resolve()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-31
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2013-05-07
    • 2021-08-18
    相关资源
    最近更新 更多