在 JavaScript/TypeSctipt 中创建自定义 Promise 的真实示例
在 JavaScript 的世界里,我们感觉已经完全从回调转向了Promises和async/await 。如此之多,以至于几乎每个库和框架都提供了异步版本的函数。其逻辑通常是这样的:“我看到async -> 我输入await并将我的函数也标记为async -> 完成!”。我已经太习惯了,以至于我开始忘记如何创建和使用自己的Promises 了。
但生活总会以某种方式提醒你,旧习难改,特别是当你谈论浏览器 API 时。
因此,如果您像我一样,需要一些关于如何做出自定义承诺的提醒,我希望您会发现这篇文章很有帮助。
创建 html 图像。
问题就在这里。我们需要使用浏览器的 API 创建一个 Image 元素,并将其源设置为某个图片的 dataUrl。起初,我是这样写的:
function drawImage(dataUrl: string) {
const image = new Image();
image.src = dataUrl;
return image;
};
看起来不错,但这里有一个问题。当我们设置image.src
它时,它不会立即加载。即使源是一个数据字符串,而不是指向外部资源的 URL,它仍然需要时间。因此,当函数返回一张图片时,并不能保证数据已经存在。
不幸的是,如果您想等待加载完成,您就不能做这样的事情。
function drawImage(dataUrl: string) {
const image = new Image();
await image.src = dataUrl; // STOP! THIS IS ILLEGAL!
return image;
};
唯一的方法是设置事件处理程序。但是我们该在这里放什么呢?
function drawImage(dataUrl: string) {
const image = new Image();
image.addEventListener('load', () => {
// ???
});
image.src = dataUrl;
return image;
};
如果我们仍处于 2010 年,我们会通过为回调函数添加另一个参数来解决这个问题。
function drawImage(dataUrl: string, onDone: () => void) {
const image = new Image();
image.addEventListener('load', () => {
onDone();
});
return image;
};
等等,都2021年了,现在的年轻人可不会再这么做了。我们需要的是让函数返回一些可等待的东西。没有什么比Promise更可等待的了。这是Promise 的构造函数
function Promise<T>(
executor: (
resolve: (value: T) => void,
reject: (reason?: any) => void
) => void
)
看起来有点吓人,不过你只需要更了解它就行了。通常你都是这么叫它的。
const promise = new Promise((resolve, reject) => {
// Lalala, do some work
// ....
if (we_are_good_and_got_the_result) {
resolve(result);
} else {
reject(error);
}
})
所以你在构造函数中传递了一个函数。这个函数有两个参数,它们也是函数。分别调用resolve
和reject
。在这个函数中,我们执行一些操作。如果一切顺利,就调用 并resolve
传入结果。否则,调用 并传入一个错误对象。
你传入的参数在解析后resolve
会以Promise 的形式返回。
然后您就可以使用这个新对象了。
promise.then((result) => {
// Use the result
}).catch(error => {
// Oh no there was an error
})
而且,更好的是,你也可以做到这一点。
const result = await promise;
让我们将学到的知识应用到我们的问题中。
function drawImage(dataUrl: string) {
const promise = new Promise<HTMLImageElement>((resolve, reject) => {
const image = new Image();
image.addEventListener('load', () => {
resolve(image);
}, { once: true }); // We don't want this handler to run more than once.
image.src = dataUrl;
});
return promise;
}
然后您可以使用 调用新函数await
。
const image = await drawImage('data');
就这样,我们成功了!
对于那些等不及的人来说,这是一个额外的例子。
这是我再给大家展示一个例子。能够等待一段时间其实挺有用的。可惜的是,JavaScript 中没有wait()
orsleep()
函数。不过,有了这些新技能,我们可以自己写一个。这里有一个快速的单行代码,大家可以试着做做练习(我感觉自己像个大学老师一样,哈哈)。
const wait = async (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
请向我展示更多,前辈。
本文实际上是我最新博文摘录的扩展版。如果你想了解更多,欢迎查看 ;)。
文章来源:https://dev.to/nordicbeaver/a-real-life-example-of-making-a-custom-promise-in-javascript-typesctipt-5d1n