OOP Javascript use Promise and problems with "this" - javascript

When designing OOP ES 5-6, where I combine prototypes with ES 6 functions. Everything is running in ElectronJS, I do not want a new version that fully supports ES 7 too, so for example the definition of import {trida} from "./cesta" must be solved require ('./ path'). My problem, but it's in Promise.
If I want to program object, I want every object to do what it has and pass the result to the main branch of the program, which contains the column of the whole procedure - object list - Content. If fun enter setTimeout (), you need to use the Promise here, which waits until the function is executed and continues to call another object.
let importing = function(){
this.name = "boot";
}
importing.prototype.start = function(resolve){
this.resolve = resolve;
setTimeout(this.test.bind(this),1000);
console.log('start -------->');
}
importing.prototype.test = function(){
this.resolve('Test');
console.log('Test -------->');
}
importing.prototype.end = function(resolve){
console.log('end -------->');
this.resolve = resolve;
this.resolve('end');
}
let geko;
let scan = new importing();
Promise.resolve(geko)
.then((geko) => new Promise(scan.start.bind(scan)))
.then((geko) => new Promise(scan.end.bind(scan)))
.catch(geko => {
console.log('Error message: ',geko)
})
Here is the problem, I do not want the features to nest in the prototype functions, I want to call every object, nicely in order, clearly. Like any book, it has its Chapter Content, and then the chapters itself and I want to have a quick entry into what I have programmed and did not look at how much a mouse was taken after a week. But for this operation, besides Promise, I also have to use the bind () function because:
importing.prototype.start = function(){
// here this acts as a window object not as importing
// why I have this object called scan.start.bind (scan)
// and here again in setTimeout i have to bind (this) to get it in this.test
// could access this importing - scan object
setTimeout(this.test.bind(this),300);
}
You would find a better way??

You should not pass methods as the argument to the new Promise constructor. If the method is asynchronous, it should return a promise by itself; if it's not asynchronous then you shouldn't be using any promises.
function importing(){
this.name = "boot";
}
importing.prototype.start = function() {
console.log('start -------->');
return new Promise(resolve => {
setTimeout(resolve, 1000); // put the native async call in here, and nothing else!
}).then(() =>
this.test()
);
};
importing.prototype.test = function() {
console.log('Test -------->');
return 'Test';
};
importing.prototype.end = function() {
console.log('end -------->');
return 'end';
}
const scan = new importing();
scan.start().then(() => scan.end()).catch(geko => {
console.log('Error message: ',geko)
});

If the whole project was created as follows:
return new Promise(resolve => {
setTimeout(resolve, 1000);
}).then(() =>
this.test()
);
I would not have much to do with the classic JS procedure, ie the nesting of functions in the functions. That's what I want to avoid. I want content, an outline, when I look at it for a year and I'm going to solve the bugs, I'll know where to start and where the mistakes are going.
let importing = function(){
this.name = "boot";
}
importing.prototype.start = function(resolve){
console.log('Start');
this.resolve = resolve;
setTimeout(this.test.bind(this),1000);
}
importing.prototype.test = function(){
console.log('Test');
this.resolve('Test');
}
importing.prototype.end = function(resolve){
console.log('End');
resolve('end');
}
let scan = new importing();
let promise = function(arg){
return new Promise((resolve, reject)=>{ // The same: new Promise(scan[arg].bind(scan))
return scan[arg].bind(scan)(resolve)
});
}
// so I would imagine chaining. Few braces, simply
// In each called object, if possible, the minimum promissory note
Promise.resolve()
.then(geko => promise('start'))
.then(geko => promise('end'))
.catch(geko => {
console.log('Error message: ',geko)
})

Related

Promise.resolve vs Promise.resolve().then()

A question asked here before, with the exact same title as this one, was answered with a "You should not use that, use this instead", I am looking to know what it does, not what else could I do, it's about understanding not a simple copy a paste.
My question is quite simple, what is the difference between these three approaches when creating a promise?
const API = (item, fail) =>
new Promise((resolve, reject) => {
if (fail) reject(item + ' ...with an error');
setTimeout(() => resolve(item), 1000);
});
(async () => {
const pro1 = Promise.resolve(API('I am inside resolve'));
const pro2 = Promise.resolve(API('I am inside resolve', true));
const pro3 = Promise.resolve().then(() => API('I am thenable'));
const pro4 = Promise.resolve().then(() => API('I am thenable', true));
const pro5 = new Promise((resolve) => resolve(API('I am a new promise')));
const pro6 = new Promise((resolve) => resolve(API('I am a new promise', true)));
const store = [pro1, pro2, pro3, pro4, pro5, pro6];
const results = await Promise.allSettled(store);
for (const { status, value, reason } of results) {
if (status === 'fulfilled') console.log(value)
else console.log(reason)
}
})();
The difference is in job to be done. While all of this methods are valid, they have different cost and predictability.
Promise.resolve() produces single resolved Promise instance, and depending on value provided to the call JS engine have information to optimize it. It makes all work to be done in a single call to underlying code of the JS engine (usually C++, but could be Java or WASM). So it's always the best choice.
Promise.resolve().then(() => API(/*...*/)) Produce several Promise instances: one at Promise.resolve() and other at .then() call. It also allocates more memory and make several (3 or more) redundant jumps between JS and the engine. It's hardly optimizable and requires intensive heuristics to be performed to figure out is this call optimizable. It's the worst option.
new Promise((resolve) => resolve(API(/* ... */)) allocates one function and one Promise instance and makes two jumps between JS and the engine. It's harder to optimize this call, due to nature of JS.
Promise.resolve().then()
In your examples, the then() makes no difference as you just resolve the promise, and get its data.
then() is typically used to chain promises, take this as an example:
Promise.resolve('foo')
// 1. Receive "foo", concatenate "bar" to it, and resolve that to the next then
.then(function(string) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
string += 'bar';
resolve(string);
}, 1);
});
})
// 2. receive "foobar", register a callback function to work on that string
// and print it to the console, but not before returning the unworked on
// string to the next then
.then(function(string) {
setTimeout(function() {
string += 'baz';
console.log(string); // foobarbaz
}, 1)
return string;
})
Here we chain multiple promises then() off of a previously resolved promise, while maintaining the original data from the first resolve, though in this case we modify it with every new promise.
You can read more about promises and chaining here.

Resolve promise on array push - javascript

I'm attempting to define a function that returns a promise. The promise should resolve when a given array is set (push()).
To do this I'm attempting to use a Proxy object (influenced by this):
let a = []
;(async function(){
const observe = array => new Promise(resolve =>
new Proxy(array, {
set(array, key, val) {
array[key] = val;
resolve();
}
}));
while(true){
await observe(a);
console.log(new Date().toLocaleTimeString(),"Blimey Guv'nor:",`${a.pop()}`);
}
})(a);
;(async function(){
await new Promise(resolve => timerID = setTimeout(resolve, 2000))
a.push('ʕ·͡ᴥ·ʔ');
a.push('¯\(°_o)/¯ ')
})(a)
I can't see why this doesn't work. Does anyone have any idea?
More generally, what is a good way to have a promise resolve on push to an array?
The problems with your attempt:
you invoke .push on the original array, not the proxied one. Where you create the proxy, it is returned to no-one: any reference to it is lost (and will be garbage collected).
The code following after the line with await will execute asynchronously, so after all of your push calls have already executed. That means that console.log will execute when the array already has two elements. Promises are thus not the right tool for what you want, as the resolution of a promise can only be acted upon when all other synchronous code has run to completion. To get notifications during the execution synchronously, you need a synchronous solution, while promises are based on asynchronous execution.
Just to complete the answer, I provide here a simple synchronous callback solution:
function observed(array, cb) {
return new Proxy(array, {
set(array, key, val) {
array[key] = val;
if (!isNaN(key)) cb(); // now it is synchronous
return true;
}
});
}
let a = observed([], () =>
console.log(new Date().toLocaleTimeString(),"Blimey Guv'nor:", `${a.pop()}`)
);
a.push('ʕ·͡ᴥ·ʔ');
a.push('¯\(°_o)/¯ ');
As noted before: promises are not the right tool when you need synchronous code execution.
When each push is executed asynchronously
You can use promises, if you are sure that each push happens in a separate task, where the promise job queue is processed in between every pair of push calls.
For instance, if you make each push call as part of an input event handler, or as the callback for a setTimeout timer, then it is possible:
function observed(array) {
let resolve = () => null; // dummy
let proxy = new Proxy(array, {
set(array, key, val) {
array[key] = val;
if (!isNaN(key)) resolve();
return true;
}
});
proxy.observe = () => new Promise(r => resolve = r);
return proxy;
}
let a = observed([]);
(async () => {
while (true) {
await a.observe();
console.log(new Date().toLocaleTimeString(),"Blimey Guv'nor:",`${a.pop()}`);
}
})();
setTimeout(() => a.push('ʕ·͡ᴥ·ʔ'), 100);
setTimeout(() => a.push('¯\(°_o)/¯ '), 100);

Listen for when promise resolves inside executor function

return new Promise(function(resolve, reject {
const to = setTimeout(function(){
});
});
imagine that I want to make sure resources are cleaned up from inside the executor function.
I would like to do something like this:
return new Promise(function(resolve, reject {
const to = setTimeout(function(){
});
this.finally(function(){
clearTimeout(to);
});
});
but this is not a available in a promise executor function.
Is there some way to clean up async resources in a promise executor?
I guess you could clean them up before call resolve/reject, but there are a few cases where that is harder.
Not sure if you need to clear the timeout after it fired but you could try the following:
var someTest = () => {
var t;
var p = new Promise(
(resole)=>{
t = setTimeout(resole,2000)
}
);
p.finally(
()=>console.log(t,clearTimeout(t))
)
return p;
}
someTest();
Or you could try the following:
var someTest = () =>
new Promise(
(resole)=>{
t = setTimeout(resole,2000)
}
).then(
result=>{
//clean up
return result
},
error=>{
//clean up
return Promise.reject(error)
}
);
From inside the promise executor, you can't get access to the promise. It hasn't been assigned yet to anything that your code can reach.
So, you have two options.
You can put your cleanup code outside the executor where you can access the returned promise with p.finally(). You will then have to also keep track of your resources outside the executor also (which is perhaps inconvenient).
You can replace the resolve() and reject() callbacks with your own stub that does your cleanup, then calls the actual resolve() or reject().
You can use a Deferred object which allows you to call resolve/reject from outside the promise executor thus giving you access to p.finally() and resolve() and reject() all in the same scope (which is really the source of the original challenge).
Here's an example of option #2:
return new Promise(function(rv, rj) {
// have to try/catch here because an execption will automatically reject
// without us having seen it
try {
// declare wrappers that should be called by code in this executor
// do not call rv() and rj() directly
function resolve(arg) {
finally();
rv(arg);
}
function reject(arg) {
finally();
rj(arg);
}
// cleanup code that is only ever called once
let finallyCalled = false;
function finally() {
if (!finallyCalled) {
clearTimeout(to);
finallyCalled = true;
}
}
const to = setTimeout(function(){
});
// elsewhere in this executor it should call resolve() or reject()
} catch(e) {
reject(e);
}
});
Here's an example of option #3.
Deferred objects are generally not recommended, but they do give you access to .finally(), resolve() and reject() all in the same scope which does make some things cleaner (like what you're trying to do).
First a simple promise wrapper that gives us a Deferred object:
// can be used as either:
// let d = Promise.Deferred();
// let d = new Promise.Deferred();
// d.then(...)
// d.resolve(x);
// d.finally(...)
Promise.Deferred = function() {
if (!(this instanceof Promise.Deferred)) {
return new Promise.Deferred();
}
let p = this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
this.then = p.then.bind(p);
this.catch = p.catch.bind(p);
this.finally = p.finally.bind(p);
}
Then, you could use it like this:
// usage
function yourFunction() {
let d = new Promise.Deferred();
const to = setTimeout(...);
// other code here that will call d.resolve() or d.reject()
// cleanup code
d.finally(function() {
clearTimeout(to);
});
return d.promise;
}
This OP describes one of the uglier snafus with Promises imo, but this might work:
return new Promise(function(resolve, reject {
const to = setTimeout(function(){
console.error('timed out');
reject('timed out');
});
doSomething(function(err, data){
if(!to._called){
resolve({to, data})
}
});
})
.then(function(v){
clearTimeout(v && v.to);
return v && v.data;
});
the problem with this solution is that callback in the then is called asynchronous, so it might be possible that the timer resolves in the interim? not sure.

Waiting for a promise before it exists

I am listening to user events and some of these depend on the completion of others. Dealing with these events is an asynchronous task, so I use promises.
Let's say I've got this:
A
-> B
-> C
-> ...
-> D
-> E
-> ...
-> F
My initial approach was to save a promise for A and attach the handling of B using the then method of A's promise. The same for B and C ... D and D and E ... F.
But these events can happen almost in the same time, and B can happen before A. Since I cannot listen to a promise that not exists yet... How would you resolve this?
My idea is to define an object for each level (A, B, D), where I can attach a promise and the handling of future events. When attaching a promise, I would iterate the handling of future events and set them to the promise's then. When attaching a future event, I would look if there is a promise, and attach that to it's then or save that into an array or something.
Do you know an existing solution that already solves this issue or shall I follow with my idea?
Thank you.
Further clarification as requested:
I'm listening to multimedia events in the client side that are forwarded via websocket (using socket.io) to the server. The order of the events is indeed first A, then B, etc. But since some of them happen almost at the same time, they can be processed out of order.
Example code
let promiseForA, promiseForB;
socket.on('A', data => {
promiseForA = asynchronousTaskForA();
});
socket.on('B', data => {
// What if promiseForA has not yet been defined?
promiseForA.then(neededValue => {
asynchronousTaskForB(neededValue);
});
});
socket.on('C', data => {
// What if promiseForB has not yet been defined?
promiseForB.then(neededValue => {
asynchronousTaskForC(neededValue);
});
});
socket.on('D', data => {
// What if promiseForB has not yet been defined?
promiseForB.then(neededValue => {
asynchronousTaskForD(neededValue);
});
});
function asynchronousTaskForA() {
// something
resolve('something needed by B');
}
function asynchronousTaskForB(value) {
// something with value
resolve('something needed by C ... D');
}
function asynchronousTaskForC(value) {
// something with value
resolve();
}
function asynchronousTaskForD(value) {
// something with value
resolve('something needed by E ... F');
}
My idea
So... it works. It may be an anti-pattern, wrong or insane, but... I'd like to know of a better alternative.
let PromiseWaiter = function() {
let promise = null;
let thens = [];
let self = this;
this.setPromise = function (p) {
promise = p;
thens.forEach(t => {
p.then(t);
});
};
this.then = function(t) {
if (promise === null) {
thens.push(t);
} else {
promise.then(t);
}
return self;
};
this.reset = function() {
promise = null;
thens = [];
};
};
module.exports = PromiseWaiter;
Using it:
let waitForA = new PromiseWaiter();
let waitForB = new PromiseWaiter();
let waitForD = new PromiseWaiter();
socket.on('A', data => {
waitForA.setPromise(asynchronousTaskForA());
});
socket.on('B', data => {
waitForA.then(neededValue => {
waitForB.setPromise(asynchronousTaskForB(neededValue));
});
});
socket.on('C', data => {
waitForB.then(neededValue => {
asynchronousTaskForC(neededValue);
});
});
socket.on('D', data => {
waitForB.then(neededValue => {
waitForD.setPromise(asynchronousTaskForD(neededValue));
});
});
// Note: I am confused why these functions did not return a Promise before
// They have always done that.
function asynchronousTaskForA() {
return new Promise((resolve, reject) => {
// something
resolve('something needed by B');
});
}
function asynchronousTaskForB(value) {
return new Promise((resolve, reject) => {
// something with value
resolve('something needed by C ... D');
});
}
function asynchronousTaskForC(value) {
return new Promise((resolve, reject) => {
// something with value
resolve();
});
}
function asynchronousTaskForD(value) {
return new Promise((resolve, reject) => {
// something with value
resolve('something needed by E ... F');
});
}
Thank you!
What if promiseForA has not yet been defined?
Just don't assign to it asynchronously. Create it immediately - make a promise for it. Oh, a promise for a promise is just a promise.
const A = new Promise(resolve => socket.on('A', resolve));
const B = new Promise(resolve => socket.on('B', resolve));
const C = new Promise(resolve => socket.on('C', resolve));
const D = new Promise(resolve => socket.on('D', resolve));
const afterA = A.then(asynchronousTaskForA);
const afterB = Promise.all([afterA, B]).then(asynchronousTaskForB);
const afterC = Promise.all([afterB, C]).then(asynchronousTaskForC);
const afterD = Promise.all([afterB, D]).then(asynchronousTaskForD);
My idea may be an anti-pattern, wrong or insane, but... it works.
Yeah. The problems I see with it is that it looks very much like a promise (or deferred), but isn't one:
setPromise is just resolve
then does register callbacks, but doesn't return a promise that waits for the callback result, so is not chainable
reset is not possible with promises1, but I'm not sure whether you really need this.
As I said in the comments, better don't roll your own solution but just use Promise. Of course you might write a helper function socket.getPromiseForNext('A') or so.
1: You can however use an implementation like Creed that supports cancellation. I suspect just creating a new instance that waits for the next event should suffice though.
You can create a promise in the return statement of then callback.
Example:
promiseA
.then( data => {
return new Promise((resolve, reject) => {
// do some job
});
})
As far as you are using node, you can use async/await approach:
async function startFlow() {
// here you sure create promise, instead of promise A
const res1 = await promiseA;
// here you sure create promise, instead of promise B
const res2 = await promiseB;
// etc...
}
// Start your functions execution
startFlow();

Javascript Promise Sequence

I want to process a number of promises in Sequence. I have a working piece of code below but I'm wondering if I have over complicated the chaining of promises. I seem to be creating a great deal of new closures and I'm scratching my head wondering if I'm missing something.
Is there a better way to write this function:
'use strict';
addElement("first")
.then(x => {return addElement("second")})
.then(x => { return addElement("third")})
.then(x => { return addElement("fourth")})
function addElement(elementText){
var myPromise = new Promise(function(resolve,reject){
setTimeout(function(){
var element=document.createElement('H1');
element.innerText = `${elementText} ${Date.now()}`;
document.body.appendChild(element);
resolve();
}, Math.random() * 2000);
});
return myPromise;
}
#TheToolBox has a nice answer for you.
Just for fun, I'm going to show you an alternative technique that uses generators that gets its inspiration from coroutines.
Promise.prototype.bind = Promise.prototype.then;
const coro = g => {
const next = x => {
let {done, value} = g.next(x);
return done ? value : value.bind(next);
}
return next();
}
Using that, your code will look like this
const addElement = elementText =>
new Promise(resolve => {
setTimeout(() => {
var element = document.createElement('H1');
element.innerText = `${elementText} ${Date.now()}`;
document.body.appendChild(element);
resolve();
}, Math.random() * 2000);
});
coro(function* () {
yield addElement('first');
yield addElement('second');
yield addElement('third');
yield addElement('fourth');
}());
There's some pretty interesting things you can do using generators with promises. They're not immediately evident here because your addElement promise doesn't resolve any actual values.
If you actually resolve some values, you could do something like
// sync
const appendChild = (x,y) => x.appendChild(y);
// sync
const createH1 = text => {
var elem = document.createElement('h1');
elem.innerText = `${text} ${Date.now()}`;
return elem;
};
// async
const delay = f =>
new Promise(resolve => {
setTimeout(() => resolve(f()), Math.random() * 2000);
});
// create generator; this time it has a name and accepts an argument
// mix and match sync/async as needed
function* renderHeadings(target) {
appendChild(target, yield delay(() => createH1('first')));
appendChild(target, yield delay(() => createH1('second')));
appendChild(target, yield delay(() => createH1('third')));
appendChild(target, yield delay(() => createH1('fourth')));
}
// run the generator; set target to document.body
coro(renderHeadings(document.body));
Worth noting, createH1 and appendChild are synchronous functions. This approach effectively allows you to chain normal functions together and blur the lines between what is sync and what is async. It also executes/behaves exactly like the code you originally posted.
So yeah, this last code example might be slightly more interesting.
Lastly,
One distinct advantage the coroutine has over the .then chaining, is that all of the resolved promises can be accessed inside the same scope.
Compare .then chains ...
op1()
.then(x => op2(x))
.then(y => op3(y)) // cannot read x here
.then(z => lastOp(z)) // cannot read x or y here
to the coroutine ...
function* () {
let x = yield op1(); // can read x
let y = yield op2(); // can read x and y here
let z = yield op3(); // can read x, y, and z here
lastOp([x,y,z]); // use all 3 values !
}
Of course there are workarounds for this using promises, but oh boy does it get ugly fast...
If you are interested in using generators in this way, I highly suggest you checkout the co project.
And here's an article, Callbacks vs Coroutines, from the creator of co, #tj.
Anyway, I hope you had fun learning about some other techniques ^__^
I am not sure why others left out a simple way out, you could simply use an array and reduce method
let promise, inputArray = ['first', 'second', 'third', 'fourth'];
promise = inputArray.reduce((p, element) => p.then(() => addElement(element)), Promise.resolve());
Your code looks close to the best you can get here. Promises can be a strange structure to get used to, especially as writing promis-ified code can often end up embedding a function in another function. As you can see here, this is a pretty common phrasing to use. There are only two stylistic changes that could possibly be made. Firstly, myPromise is unnecessary and only serves to add a confusing extra line of code. It's simpler just to return the promise directly. Secondly, you can use function binding to simplify your calls at the beginning. It may not be inside the function itself, but it does eliminate several closures. Both changes are shown below:
'use strict';
addElement("first")
.then(addElement.bind(null,"second"))
.then(addElement.bind(null,"third"))
.then(addElement.bind(null,"fourth"))
function addElement(elementText){
return new Promise(function(resolve,reject){
setTimeout(function(){
var element=document.createElement('H1');
element.innerText = `${elementText} ${Date.now()}`;
document.body.appendChild(element);
resolve();
}, Math.random() * 2000);
});
}
It's worth pointing out that, if you were willing to restructure a bit, a slightly more attractive design would take form:
'use strict';
var myWait = waitRand.bind(null,2000);
myWait
.then(addElement.bind(null, "first"))
.then(myWait)
.then(addElement.bind(null, "second"))
.then(myWait)
.then(addElement.bind(null, "third"))
function waitRand(millis) {
return new Promise((resolve, reject) => {
setTimeout(resolve, Math.random() * millis);
}
}
function addElement(elementText) {
var element = document.createElement('h1');
element.innerText = `${elementText} ${Date.now()}`;
document.body.appendChild(element);
}
This trades length of promise chain for clarity, as well as having slightly fewer nested levels.
You could simplify the use of your function by making addElement() return a function instead so it can be directly inserted into .then() handlers without having to create the anonymous function:
'use strict';
addElement("first")()
.then(addElement("second"))
.then(addElement("third"))
.then(addElement("fourth"))
function addElement(elementText){
return function() {
return new Promise(function(resolve){
setTimeout(function(){
var element=document.createElement('H1');
element.innerText = `${elementText} ${Date.now()}`;
document.body.appendChild(element);
resolve();
}, Math.random() * 2000);
});
}
}
There's not much to be done with regard to the number of closures. Nesting of functions is just something you get used to with js, and the code in the question really isn't that bad.
As others have said, writing addElement() to return a function makes for a neater main promise chain.
Going slightly further, you might consider writing the returned function with an inner promise chain, allowing the (slight) separation of promise resolution from DOM element insertion. This creates no more and no less closures, but is syntactically neater, in particular allowing you to write setTimeout(resolve, Math.random() * 2000);.
'use strict';
addElement("first")
.then(addElement("second"))
.then(addElement("third"))
.then(addElement("fourth"));
function addElement(elementText) {
return function() {
return new Promise(function(resolve, reject) {
setTimeout(resolve, Math.random() * 2000);
}).then(function() {
var element = document.createElement('H1');
document.body.appendChild(element);
element.innerText = `${elementText} ${Date.now()}`;
});
};
}
Maybe it's just me but I find this much more pleasing on the eye, albeit at the cost of an additional .then(), hence an additional promise, per addElement().
Note: If you needed to resolve the promise with a value, you are still afforded the opportunity to do so by returning a value from the chained then's callback.
Going even further, if you want the inserted elements to appear in the demanded order, not the order determined by promise settlement, then you can create/insert elements synchronously, and populate them asynchronously :
function addElement(elementText) {
var element = document.createElement('H1');
document.body.appendChild(element);
return function() {
return new Promise(function(resolve, reject) {
setTimeout(resolve, Math.random() * 2000);
}).then(function() {
element.innerText = `${elementText} ${Date.now()}`;
});
};
}
All that was necessary was to move two lines within addElement(), to change the timing of the insertions whilst leaving the element.innerText = ... line where it was. This is possible whether or not you opt for the inner promise chain.
I wrote two methods here :
Sequence = {
all( steps ) {
var promise = Promise.resolve(),
results = [];
const then = i => {
promise = promise.then( () => {
return steps[ i ]().then( value => {
results[ i ] = value;
} );
} );
};
steps.forEach( ( step, i ) => {
then( i );
} );
return promise.then( () => Promise.resolve( results ) );
},
race( steps ) {
return new Promise( ( resolve, reject ) => {
var promise = Promise.reject();
const c = i => {
promise = promise.then( value => {
resolve( value );
} ).catch( () => {
return steps[ i ]();
} );
};
steps.forEach( ( step, i ) => {
c( i );
} );
promise.catch( () => {
reject();
} );
} );
}
};
Sequence.all will run functions in a sequence until all promises in arguments are resolved. And return another Promise object with arguments as an array filled with all resolved values in sequence.
Sequence.all( [ () => {
return Promise.resolve( 'a' );
}, () => {
return Promise.resolve( 'b' );
} ] ).then( values => {
console.log( values ); // output [ 'a', 'b' ]
} );
Sequence.race will run functions in a sequence and stop running while one promise object been resolved.
Sequence.race( [ () => {
return Promise.reject( 'a' );
}, () => {
return Promise.resolve( 'b' );
}, () => {
return Promise.resolve( 'c' );
} ] ).then( values => {
console.log( values ); // output [ 'a' ]
} );

Categories

Resources