如何在我要求之前不 运行 Promise

How to not run a Promise before I ask to

我以为我对 Promise 已经完全了解了,但这个真的把我赶下了床。当使用带有两个参数的执行程序创建新的 Promise 时,为什么这个方法 运行 在我采用 then() 或 catch() 之前

运行 节点 6.2.2.

import assert = require('assert');

describe("When working with promises", () => {
    let ar = [1, 2, 3, 4, 5, 6];

    beforeEach(() => {

    })

    it("should be perfectly fine but isn't when mapping to promises", (done) => {
        ar.map(num => {
            return new Promise((resolve, reject) => {
                done(new Error('Why on earth is ' + num + ' called'));
            })
        })

        done();
    })

    it("should be perfectly fine when mapping to methods", (done) => {

        ar.map(num => {
            return (resolve, reject) => {
                done(new Error(num + ' is not called ever'));
            }
        })

        done();
    })
});

第一次测试失败,第二次测试成功。

要实现相同的行为,您必须在工厂中包装承诺。您可以为此使用 lambda 函数。

 it("should be perfectly fine but isn't when mapping to promises", (done) => {
     ar.map(num => {
         return () => new Promise((resolve, reject) => {
             done(new Error('Why on earth is ' + num + ' called'));
         })
     })

     done();
 })

所以你有无状态的工厂可以稍后调用而不会在映射期间创建承诺(运行 立即)。

它允许您compose and join Promises for later batch execution using Promise.all, Promise.race,或自定义链接。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise:

[...] The executor function is executed immediately by the Promise implementation, passing resolve and reject functions [...].

这就是 Promise 实现的方式。您还可以创建一个新的承诺,并在承诺已经成功或失败时附加链式 then()catch() 处理程序。

const p = new Promise(someExecutor);
// do some other things
p.then(someHandler);
// do some other things
p.catch(someOtherHandler);

如果您还不想让执行器执行,那么请不要将它传递给 Promise 构造器。

如果查看documentation for Promise,你会发现给构造函数的函数是运行立即。它应该启动异步计算并在那里安装两个回调(这样 resolvereject 不会立即被调用,而是在计算完成或失败时被调用)。

Promise 函数 不是 异步计算,它只是将该计算和您需要跟踪它的两个回调包装到一个漂亮的包中(并在完成此设置后立即 returns。

您的第二个示例为每个数字创建了一个匿名函数,但不调用它们中的任何一个。

why is this method running before I either take then() or catch() at that promise

Promise 不关心您是否安装任何 handlers/chains。无论是否有人在看,计算都会开始(或不开始)。

如果你只想要 运行 的东西(即不在之前)附加了一个 "then()" 处理程序,那么你可以使用普通的 then-ables ( https://promisesaplus.com/ )

var runLater = { 
  then: function(resolve, reject) { 
    var p = new Promise (...); // Creating a promise is optional
    resolve(p);  // you can return a plain value
  }
}

请注意,这不是 Promise,因此它没有 "catch" 方法。

但它可以提供给任何需要 promise 的函数:

  • `Promise.all([运行稍后])
  • return 作为当时处理的结果 .then(function() { return runLater; })
  • Promise.resolve(runLater) => 现在是 then/catch
  • 的承诺

其中任何一个都会调用 runLater.then 方法。