¿Cómo se puede acceder a una función de ejecución desconocida desde el momento de construcción de una instancia de Promise?

Resuelto user2276094 asked hace 7 meses • 2 respuestas

¿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?

user2276094 avatar Feb 16 '24 23:02 user2276094
Aceptado

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.

Bergi avatar Feb 16 '2024 17:02 Bergi

Lo que el OP intenta lograr se puede lograr parcheando la Proxyfunció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 Promisefunció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 Promisedel constructor executer.

  • envuelve el código personalizado de interceptación alrededor de la función executerde la función resolve.

Tener acceso a la función Proxydel constructor executery registrarla, así como tener acceso a los argumentos pasados ​​a la resolvefunción, podría revelar algunos de los executerdetalles 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>
Expandir fragmento

Peter Seliger avatar Feb 16 '2024 22:02 Peter Seliger