¿Cómo se puede acceder a una función de ejecución desconocida desde el momento de construcción de una instancia de Promise?
¿Es posible recuperar los detalles de implementación de una instancia de Promise? Supongamos la siguiente promesa creada...
let myPromise = new Promise(function (success, error) {
/* implementation */
}
¿Se puede acceder de alguna manera a la función anónima...
function (success, error) {
/* implementation */
}
... ¿u obtener la ubicación de la función anónima en el archivo de código?
No. El objeto de promesa no contiene el código, ni internamente ni accesible para JavaScript. Una promesa representa el resultado de una tarea, no la tarea en sí, no se puede ejecutar . La función se utiliza sólo durante la construcción.
Lo que el OP intenta lograr se puede lograr parcheando la Proxy
función global antes de que cualquier otro código comience a usarla.
El siguiente código de ejemplo proporcionado, con fines de demostración, extiende un enfoque de intercepción e introspección de sobrescritura y envoltura de funciones hasta donde sea posible.
Hay que hacer tres cosas...
reasigna la
Promise
función constructora con una versión proxy de sí misma, donde la invocación de su[[Construct]]
ranura interna se maneja mediante un código personalizado.envuelve el código personalizado de interceptación alrededor de la función
Promise
del constructorexecuter
.envuelve el código personalizado de interceptación alrededor de la función
executer
de la funciónresolve
.
Tener acceso a la función Proxy
del constructor executer
y registrarla, así como tener acceso a los argumentos pasados a la resolve
función, podría revelar algunos de los executer
detalles de implementación de la función, pudiendo así proporcionar algunas pistas sobre dónde profundizar a continuación.
// - The actual use case, an asynchronously implemented
// `wait` functions which resolves after the provided
// amount of milliseconds.
// - It uses the proxied version of the before created
// and reassigned global `Proxy` constructor function.
async function waitForResolvedData(valueInMSec) {
console.log('... executing ...\n\n');
return new Promise(resolve =>
setTimeout(resolve, valueInMSec, { foo: 'Foo', bar: 'Bar'})
);
}
(async () => {
console.log('waiting ...');
const data = await waitForResolvedData(3000);
console.log('\n... awaited data ...', data);
})();
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
// - reassign the `Promise` constructor function
// with a proxied version of itself, where the
// invocation of its internal `[[Construct]]`
// slot gets handled.
window.Promise = (Promise => {
const handlers = {
construct(target, [executer]) {
console.log(
`\`${ target.name }\` creation with following \`executer\` function ...\n`, executer
);
// - wrap intercepting custom code around the
// `Promise` constructor's `executer` function.
executer = (proceed => {
return ((/*resolve, reject*/...args) => {
let [ resolve, reject ] = args;
// - wrap intercepting custom code around the
// `executer` function's `resolve` function.
resolve = (proceed => {
return ((...args) => {
console.log('`\nresolve` function intercepted with following args ...\n', args);
console.log('original `resolve` function ...\n', proceed);
proceed(...args);
});
})(resolve);
console.log('`executer` intercepted with following args ...\n', args);
console.log('original `executer` function ...\n', proceed);
proceed(resolve, reject);
});
})(executer);
return new target(executer);
},
};
return new Proxy(Promise, handlers);
})(window.Promise);
</script>