为什么我的链式承诺会被阻止?

时间:2018-06-12 20:05:57

标签: javascript promise

我有一个类方法,它将类中的其他方法链接在一起,并且还在类的另一个实例上调用一个方法:

class Thing {
    doSomething(nextThing) {
        return new Promise((resolve) =>
            this.initialize()
                .then(() => this.doA())
                .then(() => {
                    nextThing.initialize(); // call initialize() on another instance
                    return this.doB();
                })
                .then(() => this.doC())
                .then(resolve)
        );
    }

    initialize() {
        return new Promise((resolve) => {
            // take a long time to do something
            // ...
            // ...
            resolve();
        });
    }

    doA() { return new Promise((resolve) => resolve()); }

    doB() { return new Promise((resolve) => resolve()); }

    doC() { return new Promise((resolve) => resolve()); }
}

const thing1 = new Thing();
const thing2 = new Thing();

thing1.doSomething(thing2);

在另一个类实例上调用该函数会锁定链的流;但是; this.doB()nextThing.initialize()会同时运行(根据需要),但this.doC()会一直运行,直到nextThing.initialize()解决。

通过nextThing.initialize()this.doB()同时启动并确保在this.doC()结算后立即启动this.doB(),确保按预期流动的正确方法是什么?如果nextThing.initialize()this.doC()之后解析,则可以。

1 个答案:

答案 0 :(得分:3)

执行此结构时:

return new Promise(resolve => {
    // run some long synchronous piece of code
    resolve(...);
});

这里发生了什么。

  1. 创建新的承诺对象
  2. 作为promise构造函数执行的一部分,将同步调用promise执行程序回调
  3. 您的长时间运行的同步代码称为om执行程序回调
  4. 您致电resolve(...)以解决之前创建的承诺
  5. 您从promise executor返回
  6. promise构造函数返回
  7. 从主函数返回,此函数调用后的代码行将运行
  8. 稍后(在当前Javascript将控制权返回给系统之后),.then()处理程序将在之前的承诺上被调用。
  9. 因此,promise会同步调用执行程序回调。它不允许你在后台运行任何东西"。 Javascript仍然是单线程的。

    您无法使用承诺将同步代码转换为异步代码。您可以使用一些承诺技术来更改代码运行时的调度,但Javascript中的同步代码仍然是同步的,并且无论何时运行,都会阻止Javascript中的代码。

    Promise纯粹是一个通知系统,用于在某些其他操作告知承诺现在已解决或拒绝时通知您。他们不会将同步代码神奇地转换为异步代码。

    所以,最重要的是,你不能使用promises来获取同步的,长时间运行的initialize()函数,并以某种方式使其成为非阻塞或异步。

      

    确保此流程按预期流动的正确方法是什么,同时启动nextThing.initialize()和this.doB(),

    如果nextThing.initialize()同步且阻止,则无法与任何内容同时运行。 node.js运行您的Javascript单线程。一次运行一个Javascript。承诺无法改变这一点。

      

    并在this.doB()解析后立即启动this.doC()

    由于this.doB()this.doC()都返回promise,然后使用链式.then()处理程序链接promises以对这些操作进行排序。您的代码似乎已经这样做了。

    有关在当前node.js单个Javascript线程之外卸载长时间运行的同步代码的选项的信息,请参阅其他答案:

    Make time intensive function asynchronous

    仅供参考,也许这只是伪代码,但这并不是理由:

    return new Promise((resolve) => resolve());
    

    你可以改为:

    return Promise.resolve();.