Reputation: 103
I'm trying to call a chain of promises sequentially. I would like to pass some state across all the promises. I thought I'd be able to bind()
my state but have been unable to get it working. My sample code looks like:
var Promise = require('bluebird');
...
function op1(state) {
return new Promise(function(resolve, reject) {
this.num += 1;
resolve();
});
}
function op2(state) {
return new Promise(function(resolve, reject) {
this.num += 1;
resolve();
});
}
function op3(state) {
return new Promise(function(resolve, reject) {
this.num += 1;
resolve();
});
}
function sequence(tasks, state) {
var current = Promise.cast();
for (var k = 0; k < tasks.length; ++k) {
current = current.thenReturn().then(tasks[k]);
}
return current.thenReturn();
}
var state = { yadda: "yadda",
num: 0 };
var q = [ op1, op2, op3 ];
var p = sequence( q, state );
var ret = p()
.then( function(val) {
console.log(val);
})
.catch ( function(val) {
console.error(val);
});
I've tried to simplify the problem to what I see in many example:
op1().bind(state).then(op2).then(op3);
However, this isn't working either.
I've also tried to change sequence()
to the following (among various other things):
var current = Promise.cast().bind(state);
I am still very new to promises. I suspect I am missing something easy. Any advice or help would be much appreciated.
Upvotes: 1
Views: 603
Reputation: 4266
Ok, let's see what could be done.
We could start with binding state
to each task.
function sequence(tasks, state) {
var current = Promise.resolve();
for (var k = 0; k < tasks.length; ++k) {
const taskWithState = tasks[k].bind(state);
current = current.then(taskWithState);
}
return current;
}
I've used bind
to set this
inside tasks to state
, so:
function op1() {
// this === state
return new Promise(function(resolve) {
// this === window
this.num += 1;
resolve();
});
}
As You might expect, a function that we pass to Promise creates its own context, so this
would not point to state
like we want it to.
To bypass that issue we could either do an old trick with saving context in a variable (like var that = this
) or we could just use arrow functions, which do not create their own context. With that in mind:
function op1() {
// this === state
return new Promise(resolve => {
// this === state
this.num += 1;
resolve();
});
}
function op1() {
return new Promise(resolve => {
this.num += 1;
resolve();
});
}
function op2() {
return new Promise(resolve => {
this.num += 1;
resolve();
});
}
function op3() {
return new Promise(resolve => {
this.num += 1;
resolve();
});
}
function sequence(tasks, state) {
let current = Promise.resolve();
for (let k = 0; k < tasks.length; ++k) {
const taskWithState = tasks[k].bind(state);
current = current.then(taskWithState);
}
return current;
}
var state = { yadda: "yadda", num: 0 };
var q = [ op1, op2, op3 ];
sequence(q, state)
.then(() => console.log(state))
.catch(err => console.error(err));
Upvotes: 1