如何使用 Promises 实现流畅的接口?
How to implement a fluent interface with Promises?
我想让这段代码起作用
$('start') // push initial value to an array
.addItem(2) // add another value
.printAll() // print everything in array
.delay(2000) // wait x seconds
.addItem(5)
.printAll()
.start(); // execute all the commands before this line
我创建了一个 class 数据数组来保存项目。和 steps 数组来保存操作。然后我使用可链接的承诺来执行它们。这是实现我想要实现的目标的最佳方式吗?我真的需要将操作存储在数组中吗?
class Sync {
constructor() {}
init(startValue) {
this.data = [startValue];
this.steps = [];
return this;
}
addItem(value) {
const append = (v)=>this.data.push(v);
this._addStep(append, value);
return this;
}
printAll() {
this._addStep(v=>console.log(v.join()), this.data);
return this;
}
delay(value) {
this._addStep(window.setTimeout, value);
return this;
}
_addStep(fun, ...args) {
this.steps.push({
fun,
args
});
}
start() {
let start = Promise.resolve();
this.steps.forEach(({fun, args})=>{
start = start.then(()=>{
return new Promise(resolve=>{
if (fun === window.setTimeout) {
setTimeout(resolve, ...args);
} else {
fun.apply(this, args);
resolve();
}
}
);
}
);
}
);
return this;
}
}
const lib = new Sync();
const $ = lib.init.bind(lib);
$('start')
.addItem(2)
.printAll()
.delay(2000)
.addItem(5)
.printAll()
.start();
虽然你的问题在我看来属于https://codereview.stackexchange.com/,但我试着想出另一种没有 Promises 的实现。它仅适用于闭包和回调:
class Sync {
constructor() {}
init(startValue) {
this.data = [startValue];
this.steps = [];
return this;
}
addItem(value) {
const append = v => this.data.push(v);
this._addStep(append, value);
return this;
}
printAll() {
this._addStep(v => console.log(v.join()), this.data);
return this;
}
delay(value) {
this._addStep(window.setTimeout, value);
return this;
}
_addStep(fun, ...args) {
this.steps.push({
fun,
args
});
}
start() {
let finalFunction;
this.steps.reverse().forEach(({ fun, args }) => {
if (fun === window.setTimeout) {
finalFunction = finalFunction ? encloseFunctionWithArgs(null, null, finalFunction, next => setTimeout(next, ...args)) : null;
} else {
finalFunction = encloseFunctionWithArgs(fun, args, finalFunction);
}
});
finalFunction();
return this;
}
}
function encloseFunctionWithArgs(fun, args, next, trigger) {
return function () {
if (fun)
fun(args);
if (next)
trigger ? trigger(next) : next();
}
}
const lib = new Sync();
const $ = lib.init.bind(lib);
$('start')
.addItem(2)
.printAll()
.delay(2000)
.addItem(5)
.printAll()
.start();
编辑
我终于实现了你想要的:
const base = {
init(startValue) {
this.promise = new Promise(resolve => this.start = resolve).then(() => [startValue]);
return this;
},
addItem(value) {
this.promise = this.promise.then(v => [...v, value]);
return this;
},
printAll() {
this.promise.then(v => v.join()).then(console.log);
return this;
},
delay(value) {
this.promise = this.promise.then(v => new Promise(resolve => setTimeout(() => resolve(v), value)));
return this;
}
}
const factory = base => arg => Object.create(base).init(arg);
const $ = factory(base);
$('start')
.addItem(2)
.printAll()
.delay(2000)
.addItem(5)
.printAll()
.start();
我想让这段代码起作用
$('start') // push initial value to an array
.addItem(2) // add another value
.printAll() // print everything in array
.delay(2000) // wait x seconds
.addItem(5)
.printAll()
.start(); // execute all the commands before this line
我创建了一个 class 数据数组来保存项目。和 steps 数组来保存操作。然后我使用可链接的承诺来执行它们。这是实现我想要实现的目标的最佳方式吗?我真的需要将操作存储在数组中吗?
class Sync {
constructor() {}
init(startValue) {
this.data = [startValue];
this.steps = [];
return this;
}
addItem(value) {
const append = (v)=>this.data.push(v);
this._addStep(append, value);
return this;
}
printAll() {
this._addStep(v=>console.log(v.join()), this.data);
return this;
}
delay(value) {
this._addStep(window.setTimeout, value);
return this;
}
_addStep(fun, ...args) {
this.steps.push({
fun,
args
});
}
start() {
let start = Promise.resolve();
this.steps.forEach(({fun, args})=>{
start = start.then(()=>{
return new Promise(resolve=>{
if (fun === window.setTimeout) {
setTimeout(resolve, ...args);
} else {
fun.apply(this, args);
resolve();
}
}
);
}
);
}
);
return this;
}
}
const lib = new Sync();
const $ = lib.init.bind(lib);
$('start')
.addItem(2)
.printAll()
.delay(2000)
.addItem(5)
.printAll()
.start();
虽然你的问题在我看来属于https://codereview.stackexchange.com/,但我试着想出另一种没有 Promises 的实现。它仅适用于闭包和回调:
class Sync {
constructor() {}
init(startValue) {
this.data = [startValue];
this.steps = [];
return this;
}
addItem(value) {
const append = v => this.data.push(v);
this._addStep(append, value);
return this;
}
printAll() {
this._addStep(v => console.log(v.join()), this.data);
return this;
}
delay(value) {
this._addStep(window.setTimeout, value);
return this;
}
_addStep(fun, ...args) {
this.steps.push({
fun,
args
});
}
start() {
let finalFunction;
this.steps.reverse().forEach(({ fun, args }) => {
if (fun === window.setTimeout) {
finalFunction = finalFunction ? encloseFunctionWithArgs(null, null, finalFunction, next => setTimeout(next, ...args)) : null;
} else {
finalFunction = encloseFunctionWithArgs(fun, args, finalFunction);
}
});
finalFunction();
return this;
}
}
function encloseFunctionWithArgs(fun, args, next, trigger) {
return function () {
if (fun)
fun(args);
if (next)
trigger ? trigger(next) : next();
}
}
const lib = new Sync();
const $ = lib.init.bind(lib);
$('start')
.addItem(2)
.printAll()
.delay(2000)
.addItem(5)
.printAll()
.start();
编辑
我终于实现了你想要的:
const base = {
init(startValue) {
this.promise = new Promise(resolve => this.start = resolve).then(() => [startValue]);
return this;
},
addItem(value) {
this.promise = this.promise.then(v => [...v, value]);
return this;
},
printAll() {
this.promise.then(v => v.join()).then(console.log);
return this;
},
delay(value) {
this.promise = this.promise.then(v => new Promise(resolve => setTimeout(() => resolve(v), value)));
return this;
}
}
const factory = base => arg => Object.create(base).init(arg);
const $ = factory(base);
$('start')
.addItem(2)
.printAll()
.delay(2000)
.addItem(5)
.printAll()
.start();