为什么我的连锁承诺被阻止? [英] Why is my chained promise blocking?

查看:37
本文介绍了为什么我的连锁承诺被阻止?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a class method that chains together other methods in the class, and also calls a method on another instance of the class:

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()解决.

Calling the function on the other class instance locks up the flow of the chain, however; this.doB() and nextThing.initialize() will run simultaneously (as desired), but this.doC() won't run until nextThing.initialize() has resolved.

什么是正确的方式来确保它按预期方式流动,同时 nextThing.initialize() this.doB()同时启动,并启动 this.doC() this.doB()解析后立即出现?没关系,如果 nextThing.initialize() this.doC()之后解析.

What's the right way to make sure this flows as expected, with nextThing.initialize() and this.doB() starting simultaneously, and starting this.doC() immediately after this.doB() resolves? It's okay if nextThing.initialize() resolves after this.doC().

推荐答案

执行此结构时:

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

这就是发生的事情.

  1. 已创建一个新的Promise对象
  2. promise executor回调是在promise构造函数执行过程中同步调用的
  3. 您长时间运行的同步代码称为executor回调
  4. 您调用 resolve(...)来解决先前创建的Promise
  5. 您从承诺执行者那里回来
  6. promise构造函数返回
  7. 您从宿主函数返回,此函数调用后的代码行将开始运行
  8. 稍后(在当前的Java脚本将控制权返回给系统之后),在先前的promise上调用 .then()处理程序.
  1. A new promise object is created
  2. The promise executor callback is called synchronously as part of the promise constructor execution
  3. Your long-running synchronous code is called om that executor callback
  4. You call resolve(...) to resolve the previously created promise
  5. You return from the promise executor
  6. The promise constructor returns
  7. You return from the host function and the line of code after this function call will get to run
  8. Sometime later (after the current piece of Javascript returns control back to the system), the .then() handlers are called on the previous promise.

因此,promise会同步调用执行程序回调.它不允许您在后台运行任何内容".Javascript仍然是单线程的.

So, a promise calls the executor callback synchronously. It doesn't allow you to "run anything in the background". Javascript is still single threaded.

您不能使用Promise将同步代码转换为异步代码.您可以使用一些promise技术来更改代码运行的时间安排,但是Javascript中的同步代码仍然是同步的,而Javascript中的阻塞代码无论何时运行都将保持同步.

You can't use a promise to make synchronous code into asynchronous code. You can use some promise techniques to change the scheduling of when code runs, but synchronous code in Javascript is still synchronous and blocking code in Javascript no matter when it runs.

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

Promises are purely a notification system for notifying you when some other operation has told a promise that it is now resolved or rejected. They don't magically convert synchronous code into asynchronous code.

因此,最重要的是,您不能使用promise来获取同步的,长期运行的 initialize()函数,并以某种方式使其成为非阻塞或异步的.

So, bottom line, you can't use promises to take a synchronous, long-running initialize() function and somehow make it non-blocking or asynchronous.

通过nextThing.initialize()和this.doB()同时启动来确保按预期方式进行流动的正确方法是什么,

What's the right way to make sure this flows as expected, with nextThing.initialize() and this.doB() starting simultaneously,

如果 nextThing.initialize()是同步且阻塞的,则它不能与任何内容同时运行.node.js运行您的Javascript单线程.一次运行一个Javascript.诺言无法改变.

If nextThing.initialize() is synchronous and blocking, it can't run simultaneous with anything. node.js runs your Javascript single threaded. One piece of Javascript running at a time. Promises can't change that.

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

and starting this.doC() immediately after this.doB() resolves

由于 this.doB() this.doC()都返回了保证,因此您将这些保证与链接的 .then()处理程序以对这些操作进行排序.您的代码似乎已经做到了.

Since this.doB() and this.doC() both return promises, then you chain the promises with chained .then() handlers to sequence those operations. Your code appears to already do that.

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

For info about options for off-loading long running synchronous code outside the current node.js single Javascript thread, see this other answer:

使时间密集型功能异步

仅供参考,也许这只是伪代码,但从来没有理由这么做:

FYI, perhaps this is just pseudo code, but there's never a reason to so this:

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

您可以改为:

return Promise.resolve();.

这篇关于为什么我的连锁承诺被阻止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆