Promise.resolve()潜在的冗余

时间:2016-06-15 20:16:43

标签: javascript node.js ecmascript-6 es6-promise

我正在开发一个现有的Restify API,它有很多这个:

return newPromise().then(function(){

   return Promise.resolve({foo:'bar'});
}).then(function(){

  return Promise.resolve({rolo:'cholo'});
}):

现在,在promise中返回Promise.resolve肯定是不必要的,但我想知道它不仅是多余的,而且如果它会损害API性能,因为最终Promise.resolve可能会被调用两次值。

所以我的问题是 - 是否优化了ES6原生承诺,以便他们不会尝试解决已经解决的承诺?换句话说,内部API是否避免调用Promise.resolve(Promise.resolve(x))

3 个答案:

答案 0 :(得分:3)

我无法谈论任何实现,但需要承诺的ES6规范seems to have a bug及其结果值每次都要解析。

答案 1 :(得分:2)

我不能谈论内部实现,但性能特征看起来大致相当 直接返回值对于Native Promises来说快2倍,对Bluebird来说要快1.1倍。这是我写的基准脚本:

<强>蓝鸟

&#13;
&#13;
var suite = new Benchmark.Suite;
suite
.add('Inner Resolve', {
    name: "Bluebird Inner Resolve",
    defer: true,
    fn: function (deferred) {
        return Promise.resolve("a")
            .then(() => Promise.resolve("b"))
            .then(() => deferred.resolve());
    }
})
.add('Bluebird Inner Return', {
    name: "Bluebird Inner Return",
    defer: true,
    fn: function (deferred) {
        return Promise.resolve("a")
            .then(() => "b")
            .then(() => deferred.resolve());
    }
})
.on('cycle', (event) => console.log(String(event.target)))
.on('complete', function onComplete () {
    console.log('Fastest is ' + this.filter('fastest').map('name'));
})
.run({ 'async': true });
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.4.0/bluebird.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.0/benchmark.min.js"></script>
&#13;
&#13;
&#13;

<强>本地

&#13;
&#13;
var suite = new Benchmark.Suite;
suite
.add('Native Inner Resolve', {
    name: "Native Inner Resolve",
    defer: true,
    fn: function (deferred) {
        return Promise.resolve("a")
            .then(() => Promise.resolve("b"))
            .then(() => deferred.resolve());
    }
})
.add('Native Inner Return', {
    name: "Native Inner Return",
    defer: true,
    fn: function (deferred) {
        return Promise.resolve("a")
            .then(() => "b")
            .then(() => deferred.resolve());
    }
})
.on('cycle', (event) => console.log(String(event.target)))
.on('complete', function onComplete () {
    console.log('Fastest is ' + this.filter('fastest').map('name'));
})
.run({ 'async': true });
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.0/benchmark.min.js"></script>
&#13;
&#13;
&#13;

您可以在此处查看Chrome的实施(https://github.com/v8/v8/blob/4.3.66/src/promise.js#L167);一些簿记似乎是在Promise.resolve中完成的,但它并没有显着影响性能。

答案 2 :(得分:0)

Promise.resolve()是一个目的有限的辅助函数,因此我不会过多地阅读其行为或性能,或者将其与承诺链接或实现中的解决方案中的内容联系起来。< / p>

FWIW,在我尝试过的所有浏览器实现中(包括Safari),我发现以下情况属实:

var p = new Promise(function() {});

console.log(Promise.resolve(p) == p);

这意味着它只会在传递承诺时返回传入的内容。冗余代码在JS中永远不会自由,但这是最小的。

这也意味着它在解决过程中的后期影响不大,因为它不会对分辨率链做出额外的承诺。

原来这种行为是explicitly specified如果IsPromise(x)基本上返回x;

我们应该不必要地调用Promise.resolve(),因为它是多余的,而不是因为任何真正的性能问题。