我有一个类方法,它将类中的其他方法链接在一起,并且还在类的另一个实例上调用一个方法:
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()
之后解析,则可以。
答案 0 :(得分:3)
执行此结构时:
return new Promise(resolve => {
// run some long synchronous piece of code
resolve(...);
});
这里发生了什么。
resolve(...)
以解决之前创建的承诺.then()
处理程序将在之前的承诺上被调用。因此,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();.