为什么这个promise解析为一个函数(unlock)?



我遵循本文中的示例https://spin.atomicobject.com/2018/09/10/javascript-concurrency/:

我们这里需要的基本上是一个互斥锁:一种表明读取集合、更新集合和写回集合的临界区不能同时发生的方式。让我们假设我们有这样一个东西[…]:

const collectionMutex = new Mutex();
async function set(collection: string, key: string, value: string): {[key: string]: string} {
return await collectionMutex.dispatch(async () => {
const data = await fetchCollection(collection);
data[key] = val;
await sendCollection(collection, data);
return data;
});
}

实现这个互斥锁需要一点承诺蹦床,但它仍然相对简单:

class Mutex {
private mutex = Promise.resolve();
lock(): PromiseLike<() => void> {
let begin: (unlock: () => void) => void = unlock => {};
this.mutex = this.mutex.then(() => {
return new Promise(begin);
});
return new Promise(res => {
begin = res;
});
}
async dispatch(fn: (() => T) | (() => PromiseLike<T>)): Promise<T> {
const unlock = await this.lock();
try {
return await Promise.resolve(fn());
} finally {
unlock();
}
}
}

Mutex类的dispatch函数中,unlock设置为await this.lock()

我的问题是:当lock()返回一个不解决任何问题的承诺时,unlock是如何以及为什么是一个函数;承诺只设置begin = res

下面是它的工作原理:

有两个承诺是用new Promise创建的。其中之一是lock返回的承诺。我们称这个承诺为P1。另一个稍后在传递给this.mutex.then的回调中创建。我们把这个promise命名为P2

res是一个函数,当被调用时,解析P1。但它不会立即被调用。相反,begin被用来引用同一个函数(begin = res),以便我们以后可以访问它。

当给this.mutex.then的回调被执行时(也就是最近的锁被释放的时候),主要的神奇发生了:

new Promise(begin)willexecutebegin。这看起来很奇怪,因为通常情况下,您会提供一个内联回调函数,在其中执行具有一些异步依赖关系的逻辑,然后让它调用resolve——这个回调函数获得的参数。但是这里begin那个回调函数。您可以通过向构造函数提供内联函数包装器,将P2承诺的创建编写得更详细,如下所示:

new Promise(resolve => begin(resolve));
如前所述,调用begin将解析P1。传递给begin参数将是承诺构造函数提供给我们的resolve函数,以便我们可以解析新的P2承诺。这个(function)参数因此成为P1的分辨率值,是的,它是一个函数。这就是await-ed表达式解析的内容。因此,unlockresolve函数,用于解析P2

最新更新