问题
I am load HTML (external app) into an iFrame
I want to "do" something (callback) when an element becomes available in my iFrame. Here how I wrote it, and I'd like to write this with Promises instead:
function doWhenAvailable(selector, callback) {
console.warn("doWhenAvailable", selector)
if ($('#myiFrame').contents().find(selector).length) {
var elt = $('#myiFrame').contents().find(selector);
console.info("doWhenAvailable Found", elt)
callback && callback(elt);
} else {
setTimeout(function() {
doWhenAvailable(selector, callback);
}, 1000);
}
}
Actually instead of using setTimeout, I'd like to use setInterval to repeat the "find element" until it's found and resolve the "promise".
回答1:
No, you would not use setInterval, you just would wrap the timeout in a promise and drop the callback:
function wait(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
function whenAvailable(selector) {
var elt = $('#myiFrame').contents().find(selector);
if (elt.length)
return Promise.resolve(elt);
else
return wait(1000).then(function() {
return whenAvailable(selector);
});
}
回答2:
Keeping your recursive style, it would have become something like that :
function doWhenAvailable(selector) {
var dfd = jQuery.Deferred();
console.warn("doWhenAvailable", selector)
if ($('#myiFrame').contents().find(selector).length) {
var elt = $('#myiFrame').contents().find(selector);
console.info("doWhenAvailable Found", elt)
return dfd.resolve(elt);
} else {
setTimeout(function() {
doWhenAvailable(selector).then(function(e) {
dfd.resolve(e);
});
}, config[env].wrapper.timeOutInMs);
}
return dfd.promise();
}
But I would have tried to avoid recursive calls here
回答3:
The general idea is to return a promise instead of receiving a callback.
Example:
var xpto = function(res) {
return new Promise((resolve, reject) => {
if(res > 0) resolve('Is greater');
else reject(new Error('is lower'));
});
}
So in your case:
function doWhenAvailable(selector) {
function work(callback) {
if ($('#myiFrame').contents().find(selector).length) {
var elt = $('#myiFrame').contents().find(selector);
console.info("doWhenAvailable Found", elt)
callback(elt);
}
}
return new Promise((resolve, reject) => {
console.warn("doWhenAvailable", selector)
setInterval(() => work(resolve), 1000);
})
}
回答4:
Here:
function doWhenAvailable(selector) {
return new Promise(function(resolve, reject){
console.warn("doWhenAvailable", selector)
if ($('#myiFrame').contents().find(selector).length) {
var elt = $('#myiFrame').contents().find(selector);
console.info("doWhenAvailable Found", elt)
resolve(elt);
} else {
setTimeout(function() {
doWhenAvailable(selector).then(function(data){
resolve(data);
});
}, config[env].wrapper.timeOutInMs);
}
}
}
And call your function like that:
doWhenAvailable("#elemId").then(function(elt){
//do what you want
});
来源:https://stackoverflow.com/questions/42673186/how-to-write-my-function-with-promises