在JavaScript中从外部解决Promise:实际应用场景

开发 前端
从外部解决Promise可以解锁强大的模式。它保持你的代码清晰和灵活,从用户操作到事件流。而像ts-deferred这样的库为我们提供了更好的处理方式。

这是JavaScript中那些在现实世界中极其强大的酷炫技巧之一。

强大的实际应用场景

动作(A)等待另一个动作(B)

A正在进行,但用户想做B,而A需要先发生。

例如:社交应用,用户可以创建、保存和发布帖子。就像Medium。

<p>
  Save status:
  <b><span id="save-status">Not saved</span></b>
</p>
<p>
  Publish status:
  <b><span id="publish-status">Not published</span></b>
</p>
<button id="save">Save</button>
<button id="publish">Publish</button>

图片图片

如果用户想在帖子保存时发布怎么办?

解决方案:确保在发布之前帖子已保存。

saveButton.onclick = () => {
  save();
};

publishButton.onclick = async () => {
  await publish();
};

let saveResolve;

let hasSaved = false;

async function save() {
  hasSaved = false;
  saveStatus.textContent = 'Saving...';
  // ✅ Resolve promise from outside
  await makeSaveRequest();
  saveResolve();
  hasSaved = true;
  saveStatus.textContent = 'Saved';
}

async function waitForSave() {
  if (!hasSaved) {
    await new Promise((resolve) => {
      saveResolve = resolve;
    });
  }
}

async function publish() {
  publishStatus.textContent = 'Waiting for save...';
  await waitForSave();
  publishStatus.textContent = 'Published';
  return;
}

图片图片

当你将这个逻辑抽象成一种Deferred类时,它变得更好:

class Deferred {
  constructor() {
    this.promise = new Promise((resolve, reject) => {
      this.reject = reject;
      this.resolve = resolve;
    });
  }
}

const deferred = new Deferred();

// Resolve from outside
deferred.resolve();

重构✅:

const deferredSave = new Deferred();
let hasSaved = false;

async function save() {
  hasSaved = false;
  saveStatus.textContent = 'Saving...';
  // 🟢 Resolve promise from outside
  await makeSaveRequest();
  saveResolve();
  hasSaved = true;
  saveStatus.textContent = 'Saved';
}

async function waitForSave() {
  if (!hasSaved) await deferredSave.promise;
}

async function publish() {
  // ...
}

它的工作方式与之前完全相同:

图片图片

Deferred更加清晰,这就是为什么我们有很多类似的NPM库:ts-deferred、deferred、promise-deferred...

图片图片

将事件流转换为Promise

这是我多次使用过的一个很好的设置。

执行一个异步任务,实际上是在内部等待事件流触发:

// data-fetcher.js
const deferred = new Deferred();

let dataDeferred;
function startListening() {
  dataDeferred = new Deferred();

  eventStream.on('data', (data) => {
    dataDeferred.resolve(data);
  });
}

async function getData() {
  return await dataDeferred.promise;
}

// client.js
const { startListening, getData } = require('./data-fetcher.js');
startListening();
// 🟢 Waits for event to happen once
const data = await getData();

最后的思考

从外部解决Promise可以解锁强大的模式。

它保持你的代码清晰和灵活,从用户操作到事件流。而像ts-deferred这样的库为我们提供了更好的处理方式。

责任编辑:武晓燕 来源: 大迁世界
相关推荐

2020-08-14 10:00:34

Node前端应用

2017-11-27 09:11:42

SSDceph应用

2011-05-17 15:24:18

Shibboleth认证

2023-11-15 13:35:00

迭代器生成器Python

2020-10-16 09:09:20

机器学习银行技术

2015-08-04 15:21:17

SDN公有云软件定义网络

2021-03-03 10:11:16

区块链商业工业

2015-04-15 14:44:06

SDN交换机云计算网络SDN

2012-10-23 09:32:07

2015-06-10 10:52:36

云计算交换机云网络

2015-06-16 13:52:25

Mesos集群管理Hadoop

2015-07-23 11:59:27

JavascriptPromise

2022-12-08 10:40:06

声明式事务AOP

2023-10-24 17:14:52

Kafka分布式系统

2021-03-31 22:37:03

数据中台企业技术

2015-05-15 10:09:48

Docker应用场景项目价值最大化

2010-12-21 16:23:34

RADVISION云视频

2010-08-31 19:45:26

DHCP server

2024-03-12 10:36:06

函数指针代码

2015-10-13 10:44:01

扁平网络EIP云网络环境
点赞
收藏

51CTO技术栈公众号