I want to override the Promise constructor and the then method in Promise.
So, whenever someone creates a new Promise object, first my code will be executed and then the original promise constructor will get called.
Similarly, when someone calls .then function of Promise, first my code will get executed and then the callback of then function will get executed.
I tried this
var bind = Function.bind;
var unbind = bind.bind(bind);
function instantiate(constructor, args) {
return new (unbind(constructor, null).apply(null, args));
}
var oldProto = Promise.prototype;
Promise = function() {
console.log("Promise instantiated");
var promise = instantiate(Promise, arguments);
return promise;
};
Promise.prototype = oldProto;
While calling this using
var myFirstPromise = new Promise((resolve, reject) => {
setTimeout(function(){
resolve("Success!"); // Yay! Everything went well!
}, 250);
});
myFirstPromise.then((successMessage) => {
console.log("Yay! " + successMessage);
});
It led to infinite loop with console filled up with Promise instantiated log. I also tried the following:
Promise = function(Promise) {
MyPromise.prototype = Promise.prototype;
function MyPromise(){
console.log("Hello");
var promise = Function.prototype.bind.apply(MyPromise, arguments);
console.log(promise);
return promise;
}
}(Promise);
But, I am not sure whether the constructor overriden is the correct way to do it and how to define the then function for Promise.
Related
I'm studying promises; can anybody explain me why this piece of code does not work is I call the
function add() inside the resolve?
<script>
async function f() {
function add() {
return 14+3;
}
let promise = new Promise((resolve, reject) => {
setTimeout(()=>{resolve(add)}, 3000); //this doesn't work
setTimeout(()=>{resolve(14+3)}, 3000); // this works
});
let result = await promise;
alert(result);
alert ("END");
}
f();
</script>
When you resolve with value you actually returning value from promise. In your example you resolve with function in arguments, so your promise returns function(function add)
So modify line,
resolve(add);
to
resolve(add());
I've been trying to understand how async/await works, all I want to do is have it wait until the value is returned. However, I could not get it to do so with callbacks nor promises nor async/await. What am I doing wrong, and why does async/await not work as I expect it to? (wait with running other code until this promise is resolved)
Many questions like this one link to "introduction pages". I've read them all, I understand what they do, I just don't know how to properly write them out, as I believe I did everything correctly, I'm just missing something
console.log("xcdcxcxcxccxvccvffdgfcd");
thing();
async function thing() {
let c = await otherthing();
console.log("dfasfadsfdasasdfa" + c)
}
async function otherthing() {
await setTimeout(function() {
return new Promise((resolve, reject) => {
let f = "rerewwqfewfasgsadf"
return resolve(f);
})
}, 3000);
}
console.log is supposed to wait until the promised value c is returned, however, it does not seem to work. Why?
Async/await works with functions that return promises. Your otherthing function doesn't return anything.
You can fix the code by returning the promise you are instantiating, like this:
thing();
async function thing() {
let c = await otherthing();
console.log("dfasfadsfdasasdfa" + c)
}
function otherthing() {
return new Promise((resolve, reject) => {
setTimeout(function () {
let f = "rerewwqfewfasgsadf"
resolve(f);
}, 3000)
});
}
You must return the new Promise from the otherthing function, not from the setTimeout callback. You are supposed to construct the promise, in its executor callback start the asynchronous action (setTimeout) and then asynchronously resolve() or reject() the promise.
function otherthing() {
return new Promise((resolve, reject) => {
setTimeout(function(){
let f = "rerewwqfewfasgsadf"
resolve(f);
}, 3000);
});
}
You don't need any async/await here for the function that is essentially only a promise wrapper around setTimeout. See also How do I convert an existing callback API to promises?.
You should move setTimeout inside Promise body and there do resolve(f)
function otherthing() {
return new Promise((resolve, reject) => {
setTimeout(() => {
let f = "rerewwqfewfasgsadf"
resolve(f);
}, 3000);
});
}
async function otherthing has no return statement, so it will always return a promise that resolves to undefined.
await setTimeout(...) doesn't make any sense. You can only await a promise, and setTimeout does not return a promise.
You need to explicitly:
create a new Promise() inside otherthing
resolve() it with the desired value inside the callback function you pass to setTimeout
return the promise from otherthing
Don't create a promise inside the callback function you pass to setTimeout. It is pointless there.
I am trying to impliment "Method Chaining" using this tutorial ( https://schier.co/blog/2013/11/14/method-chaining-in-javascript.html )
My issue is that I have to be creating an Object that uses call back API that looks like the following
function Cook() {};
Cook.prototype.readOrder = function readOrder(callback) {
setTimeout(function() {
callback()
console.log('Cook has read the order');
}, 666);
};
Cook.prototype.createOrder = function createOrder(callback) {
setTimeout(function() {
callback()
console.log('Cook has created the order');
}, 1337);
};
I want to be able to do Method chaining without altering the code above...
My approach has been to create a new Cook and wrap the callbacks in Promises.
Something like this.
function NewCook(cook){
self = this;
this.readOrder = function() {
var readOrderPromise = new Promise(function(resolve, reject) {
cook.readOrder(resolve)
})
return self
};
this.createOrder = function() {
var createOrder = new Promise(function(resolve, reject) {
cook.createOrder(resolve)
})
return self
};
};
var original = new Cook();
var newCook = new newCook(cook)
When I chain my methods together however, the second method does not wait for the first to resolve.
newCook.readOrder().createOrder()
I tried altering my code to return a promise with "Then" like the following
this.readOrder = function() {
var readOrderPromise = new Promise(function(resolve, reject) {
cook.readOrder(resolve)
}).then(function(){return self})
return readOrderPromise
};
With this code, however, I get an error saying
TypeError: Cannot read property 'createOrder' of undefined
Which makes me think that the "createOrder" method is not waiting for the "readOrder" to resolve before firing...
How do I, using Native Promises and Method Chaining, make "createOrder" wait for the promise to resolve?
To get something like:
newCook.readOrder().createOrder()
Where each method still returns the original object (for regular chaining), then you can do something like jQuery does for animations. It allows things like:
$("someSelector").slideDown(500).fade(500);
Where the .fade(500) operation does not start executing until after the .slideDown(500) operation has completed. Both are async (so the functions return immediately).
The way it works is that it creates a set of methods that can be used in a chain in this fashion and they all work through a queue. The object itself maintains a queue and every method that wishes to participate in this auto-sequencing, must queue itself and its parameters rather than directly execute. You can monitor all your operations with promises and the queue in this case can just be an actual promise chain. So, each new operation just adds itself to the end of the promise chain.
Here's an example using ES6 syntax:
class Queue {
constructor() {
this.init();
}
init() {
let oldP = this.p;
this.p = Promise.resolve();
return oldP;
}
promise() {
return this.p;
}
// takes a function that returns a promise
add(fn, ...args) {
// add this operation into our current promise chain
this.p = this.p.then(() => {
return fn.call(...args);
});
}
}
class NewCook {
constructor(cook) {
this.cook = cook;
this.q = new Queue();
}
// get current promise chain
promise() {
return this.q.promise();
}
// starts new promise chain, returns prior one
// this branches a new promise chain so new operations
// are not affected by the prior state of the promise chain
// Note that rejects are "latched" so this is required if the previous
// promise chain rejected.
init() {
return this.q.init();
}
readOrder() {
this.q.add(() => {
return new Promise((resolve, reject) => {
this.cook.readOrder(resolve);
});
});
return this;
}
createOrder(data) {
this.q.add(() => {
return new Promise((resolve, reject) => {
this.cook.createOrder(data, resolve);
});
});
return this;
}
}
var cook = new Cook();
var newCook = new NewCook(cook);
In real life where I knew more about the existing Cook, callback-based object, I'd probably "promisify" that object first in some automated fashion so I could just call promisified methods on it directly rather that repeating the promisfy code in every NewCook method.
For example, if the Cook callbacks all follow the node.js calling convention, then they can be promisified somewhat automatically using Bluebird's PromisifyAll method. If they all followed some other calling convention, I'd probably write a generic promisify method for that style that could be used instead of manually promisifying every method you want to use.
// promisify the Cook methods using Bluebird
Promise.promisifyAll(Cook);
class NewCook {
constructor(cook) {
this.cook = cook;
this.q = new Queue();
}
// get current promise chain
promise() {
return this.q.promise();
}
// starts new promise chain, returns prior one
init() {
return this.q.init();
}
readOrder() {
this.q.add(this.cook.readOrderAsync.bind(this.cook));
return this;
}
createOrder(data) {
this.q.add(this.cook.createOrderAsync.bind(this.cook), data);
return this;
}
}
var cook = new Cook();
var newCook = new newCook(cook);
1 the value can not change in promise
for example
var t = function(s) {
var wait = function(dtd) {
var dtd = $.Deferred();
//new a Deferred object in function
var tasks = function() {
alert("complete!");
s = s + "hhh";
dtd.resolve(s); // change the state of deferred object
};
setTimeout(tasks, 5000);
// return promise object
return dtd.promise(s);
};
}
var s = "hhh";
$.when(t(s))
.then(function() {
alert(s);
}).then(function() {
alert(s);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
I can only got "hhh" instead of "hhhhhh"...
2
How to invoke promise chain with different values?like a.then(b(c)).then(f(d))
I put all values in a object and then pass it on chain...
The alert in your $.when is alerting the global variable not the resolve in tasks
Also , you never call wait() and tasks() doesn't return anything.
The return of the promise only returns to wait() which never gets called. Returning to the inner function does not return to the outer function
Also you have no arguments in then() to receive the resolved data.
In order to get data to the second then, you need to return something from the first one
var t = function (s) {
var wait = function () {
var dtd = $.Deferred();
//new a Deferred object in function
var tasks = function () {
alert("complete!");
s = s + "hhh";
dtd.resolve(s); // change the state of deferred object
};
setTimeout(tasks, 2000);
// return promise object
return dtd.promise();
};
// return the promise inside `wait`
return wait()
}
var s = "hhh";
$.when(t(s)).then(function (resolvedData) {
// return to the next then...just because we can
return resolvedData; // must return something if want to access it in next then
}).then(function(previousThenData) {
alert(previousThenData);// alert argument
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
I'm new to promises and trying to wrap my head around something that should be simple. Maybe someone can hit me in the head with it instead!
I've got these two functions:
//an arbitrary method that runs on delay to mimic an async process
method1 = function( _value, _callback ){
setTimeout(function(){
console.log('dependency1_resolved');
_callback.apply(this, [{valIs:_value}]);
}.bind(this), (Math.random() * 1000));
};
//something that can simple return the object
function returnVal(x){
console.log(x); //this logs 'Object {valIs: 4}'
return x;
}
due to it's async nature, I'd like to run this function in a promise to be used later (maybe even chain later) in my code.
here is my promise:
var promise = new Promise(
function(resolve, reject) {
var x = method1(4, returnVal);
resolve(x);
}
);
promise.then(function(val) {
console.log(val); // undefined
return val;
});
console.log(promise); //Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}
Does this have anything to do with the .apply method in the first function? What am I missing? Can someone please slap me?
Your returnVal callback doesn't actually do anything.
Instead, you need to actually pass a callback that accepts the value:
var promise = new Promise(
function(resolve, reject) {
method1(4, function(x) { resolve(x); });
}
);
You can also just pass resolve itself as the callback:
var promise = new Promise(
function(resolve, reject) {
method1(4, resolve);
}
);
Your method1 does return nothing, that's why x is undefined. That the returnVal callback does return something is insignificant, its return value is simply ignored by method1.
You will need to call resolve as the callback to make your code work:
new Promise(
function(resolve, reject) {
var x = method1(4, resolve);
}
).then(function(val) {
console.log(val); // undefined
return val;
});
See also How do I return the response from an asynchronous call?