javascript - 异步链接模式
问题描述
考虑以下情况:
var Calc = function () {
// proprties
this.value = 0
// handler's
this.Add = (__value) => { this.value = this.value + __value; return this }
this.Subtract = (__value) => { this.value = this.value - __value; return this }
}
var = (new Calc()).Add(2).Subtract(1) // console.log() => 1
但是如果你将 Object 包装在 async await 中,比如
var Calc = async function () {
// proprties
this.value = 0
// handler's
this.Add = async (__value) => { this.value = this.value + __value; return this }
this.Subtract = async (__value) => { this.value = this.value - __value; return this }
}
(await new Calc()).Add(2).Subtract(1) // console.log() => undefined
(await (await new Calc()).Add(2)).Subtract(1) // console.log() => 1
我知道返回 Promise 的原因,它需要解决,因为您只需将代码包装在 () 中,一旦执行语句,您就可以继续链。
我在找什么。
await newCalc().Add(2).Subtract(1) // console.log() => 1
解决方案
await
使用只能在函数内部使用的警告,async
您想要的 API 类型是可能的,只是稍微复杂一点。
大量的库,例如knex
,jQuery
并nightmare.js
实现链式组合异步操作。但是可链接的方法不是异步的。相反,异步操作仅在操作结束时执行(当您想要结果时),但方法本身是同步的。例如knex
,异步操作仅在.then()
被调用时执行。
这是您可以做到的一种方法:
function Calc () {
this.operations = [];
this.value = 0;
}
Calc.prototype = {
add: function (x) {
// schedule a function that performs async addition:
this.operations.push(() => {
return new Promise(ok => {
ok(this.value + x);
});
});
return this;
},
subtract: function (x) {
// schedule a function that performs async subtraction:
this.operations.push(() => {
return new Promise(ok => {
ok(this.value - x);
});
});
return this;
},
// THIS IS WHERE WE DO OUR MAGIC
then: async function (callback) {
// This is finally where we can execute all our
// scheduled async operations:
this.value = 0;
for (let i=0; i<this.operations.length; i++) {
this.value = await operations[i]();
}
return callback(this.value); // since the await keyword will call our
// then method it is the responsibility of
// this method to return the value.
}
}
现在你可以像这样使用它:
async function main () {
let x = await new Calc().add(2).subtract(1);
console.log(x);
}
main();
请注意,上面的代码在功能上等同于:
new Calc().add(2).subtract(1).then(x => console.log(x));
推荐阅读
- symfony - 教义 - OnFlush 上的 getOriginalEntityData
- r - 在ggplot中使填充颜色匹配
- sap-cloud-sdk - 用于附加 odata 服务的 withServicePath 方法
- docker - AWS Fargate 启动时间
- pyqt - 如何使用带有 pyqtgraph 绘图的模型视图架构
- parsley.js - Parsley.js 无法验证当两个引导选择以一种形式出现时
- c# - 有没有办法配置 rebus DueMessageSender 频率?
- python - 在烧瓶上从“POST”路由重定向到“GET”路由
- xcode - 我的模拟器没有全屏显示
- azure - 为什么我不应该将 blob 的大小设置为 8TB 的最大大小?