¿Cómo accedo a los resultados de las promesas anteriores en una cadena .then ()?

674
Bergi 2015-02-01 00:41.

He reestructurado mi código según las promesas y he construido una maravillosa cadena de promesas planas , que consta de varias .then()devoluciones de llamada. Al final, quiero devolver algún valor compuesto y necesito acceder a múltiples resultados de promesas intermedias . Sin embargo, los valores de resolución de la mitad de la secuencia no están dentro del alcance en la última devolución de llamada, ¿cómo accedo a ellos?

function getExample() {
    return promiseA(…).then(function(resultA) {
        // Some processing
        return promiseB(…);
    }).then(function(resultB) {
        // More processing
        return // How do I gain access to resultA here?
    });
}

16 answers

391
Bergi 2015-02-01 00:44.

Romper la cadena

Cuando necesite acceder a los valores intermedios en su cadena, debe dividir su cadena en esas piezas individuales que necesita. En lugar de adjuntar una devolución de llamada y de alguna manera intentar usar su parámetro varias veces, adjunte varias devoluciones de llamada a la misma promesa, siempre que necesite el valor de resultado. ¡No lo olvides, una promesa solo representa (representa) un valor futuro ! Además de derivar una promesa de la otra en una cadena lineal, utilice los combinadores de promesas que le proporciona su biblioteca para generar el valor del resultado.

Esto dará como resultado un flujo de control muy sencillo, una composición clara de funcionalidades y, por lo tanto, una fácil modularización.

function getExample() {
    var a = promiseA(…);
    var b = a.then(function(resultA) {
        // some processing
        return promiseB(…);
    });
    return Promise.all([a, b]).then(function([resultA, resultB]) {
        // more processing
        return // something using both resultA and resultB
    });
}

En lugar de la desestructuración parámetro en la devolución de llamada después de Promise.allque sólo estaba disponible con ES6, ES5 en la thenllamada sería reemplazado por un método de ayuda ingenioso que fue proporcionado por muchas bibliotecas Promise ( Q , Bluebird , cuando , ...): .spread(function(resultA, resultB) { ….

Bluebird también cuenta con un dedicado joinfunción de reemplazar ese Promise.all+ spreadcombinación con una construcción más simple (y más económica):

…
return Promise.join(a, b, function(resultA, resultB) { … });
247
Bergi 2015-02-01 00:43.

Armonía ECMAScript

Por supuesto, este problema también fue reconocido por los diseñadores de lenguajes. Hicieron mucho trabajo y la propuesta de funciones asíncronas finalmente se convirtió en

ECMAScript 8

Ya no necesita una sola función de theninvocación o devolución de llamada, ya que en una función asincrónica (que devuelve una promesa cuando se la llama), simplemente puede esperar a que las promesas se resuelvan directamente. También presenta estructuras de control arbitrarias como condiciones, bucles y cláusulas try-catch, pero por conveniencia no las necesitamos aquí:

async function getExample() {
    var resultA = await promiseA(…);
    // some processing
    var resultB = await promiseB(…);
    // more processing
    return // something using both resultA and resultB
}

ECMAScript 6

Mientras esperábamos ES8, ya usamos un tipo de sintaxis muy similar. ES6 vino con funciones de generador , que permiten dividir la ejecución en pedazos con yieldpalabras clave colocadas arbitrariamente . Esos segmentos se pueden ejecutar uno tras otro, de forma independiente, incluso asincrónica, y eso es lo que hacemos cuando queremos esperar la resolución de una promesa antes de ejecutar el siguiente paso.

Hay bibliotecas dedicadas (como co o task.js ), pero también muchas bibliotecas de promesas tienen funciones auxiliares ( Q , Bluebird , when , ...) que hacen esta ejecución asíncrona paso a paso cuando les das una función generadora que rinde promesas.

var getExample = Promise.coroutine(function* () {
//               ^^^^^^^^^^^^^^^^^ Bluebird syntax
    var resultA = yield promiseA(…);
    // some processing
    var resultB = yield promiseB(…);
    // more processing
    return // something using both resultA and resultB
});

Esto funcionó en Node.js desde la versión 4.0, también algunos navegadores (o sus ediciones dev) admitieron la sintaxis del generador relativamente temprano.

ECMAScript 5

Sin embargo, si desea / necesita ser compatible con versiones anteriores, no puede usarlos sin un transpilador. Tanto las funciones de generador como las funciones asíncronas son compatibles con las herramientas actuales; consulte, por ejemplo, la documentación de Babel sobre generadores y funciones asíncronas .

Y luego, también hay muchos otros lenguajes de compilación en JS que se dedican a facilitar la programación asincrónica. En general, utilizan una sintaxis similar a await, (por ejemplo, helado CoffeeScript ), pero también hay otros que cuentan con una Haskell-como do-notation (por ejemplo LatteJs , monádico , Purescript o LispyScript ).

103
Esailija 2015-02-01 03:16.

Inspección sincrónica

Asignar promesas para valores necesarios posteriores a variables y luego obtener su valor mediante inspección sincrónica. El ejemplo utiliza el .value()método de bluebird, pero muchas bibliotecas proporcionan un método similar.

function getExample() {
    var a = promiseA(…);

    return a.then(function() {
        // some processing
        return promiseB(…);
    }).then(function(resultB) {
        // a is guaranteed to be fulfilled here so we can just retrieve its
        // value synchronously
        var aValue = a.value();
    });
}

Esto se puede utilizar para tantos valores como desee:

function getExample() {
    var a = promiseA(…);

    var b = a.then(function() {
        return promiseB(…)
    });

    var c = b.then(function() {
        return promiseC(…);
    });

    var d = c.then(function() {
        return promiseD(…);
    });

    return d.then(function() {
        return a.value() + b.value() + c.value() + d.value();
    });
}
58
Bergi 2015-02-01 00:42.

Anidamiento (y) cierres

El uso de cierres para mantener el alcance de las variables (en nuestro caso, los parámetros de la función de devolución de llamada de éxito) es la solución natural de JavaScript. Con las promesas, podemos anidar y aplanar arbitrariamente las .then()devoluciones de llamada; son semánticamente equivalentes, excepto por el alcance de la interna.

function getExample() {
    return promiseA(…).then(function(resultA) {
        // some processing
        return promiseB(…).then(function(resultB) {
            // more processing
            return // something using both resultA and resultB;
        });
    });
}

Por supuesto, esto está construyendo una pirámide de sangría. Si la sangría se vuelve demasiado grande, aún puede aplicar las herramientas antiguas para contrarrestar la pirámide de la fatalidad : modularizar, usar funciones con nombre adicionales y aplanar la cadena de promesa tan pronto como ya no necesite una variable.
En teoría, siempre puede evitar más de dos niveles de anidamiento (haciendo explícitos todos los cierres), en la práctica use tantos como sea razonable.

function getExample() {
    // preprocessing
    return promiseA(…).then(makeAhandler(…));
}
function makeAhandler(…)
    return function(resultA) {
        // some processing
        return promiseB(…).then(makeBhandler(resultA, …));
    };
}
function makeBhandler(resultA, …) {
    return function(resultB) {
        // more processing
        return // anything that uses the variables in scope
    };
}

También puede usar funciones auxiliares para este tipo de aplicación parcial , como _.partialde Underscore / lodash o el método nativo.bind() , para disminuir aún más la sangría:

function getExample() {
    // preprocessing
    return promiseA(…).then(handlerA);
}
function handlerA(resultA) {
    // some processing
    return promiseB(…).then(handlerB.bind(null, resultA));
}
function handlerB(resultA, resultB) {
    // more processing
    return // anything that uses resultA and resultB
}
50
Bergi 2015-02-01 00:42.

Transferencia explícita

Similar a anidar las devoluciones de llamada, esta técnica se basa en cierres. Sin embargo, la cadena permanece plana: en lugar de pasar solo el último resultado, se pasa algún objeto de estado para cada paso. Estos objetos de estado acumulan los resultados de las acciones anteriores, transmitiendo todos los valores que se necesitarán más tarde nuevamente más el resultado de la tarea actual.

function getExample() {
    return promiseA(…).then(function(resultA) {
        // some processing
        return promiseB(…).then(b => [resultA, b]); // function(b) { return [resultA, b] }
    }).then(function([resultA, resultB]) {
        // more processing
        return // something using both resultA and resultB
    });
}

Aquí, esa pequeña flecha b => [resultA, b]es la función que se cierra resultAy pasa una matriz de ambos resultados al siguiente paso. Que usa la sintaxis de desestructuración de parámetros para dividirlo en variables individuales nuevamente.

Antes de que la desestructuración estuviera disponible con ES6, .spread()muchas bibliotecas de promesas proporcionaron un ingenioso método auxiliar llamado ( Q , Bluebird , when ,…). Se necesita una función con varios parámetros, uno para cada elemento de la matriz, que se utilizará como .spread(function(resultA, resultB) { ….

Por supuesto, ese cierre necesario aquí puede simplificarse aún más mediante algunas funciones auxiliares, por ejemplo

function addTo(x) {
    // imagine complex `arguments` fiddling or anything that helps usability
    // but you get the idea with this simple one:
    return res => [x, res];
}

…
return promiseB(…).then(addTo(resultA));

Alternativamente, puede emplear Promise.allpara producir la promesa de la matriz:

function getExample() {
    return promiseA(…).then(function(resultA) {
        // some processing
        return Promise.all([resultA, promiseB(…)]); // resultA will implicitly be wrapped
                                                    // as if passed to Promise.resolve()
    }).then(function([resultA, resultB]) {
        // more processing
        return // something using both resultA and resultB
    });
}

Y es posible que no solo use matrices, sino objetos arbitrariamente complejos. Por ejemplo, con _.extendo Object.assignen una función auxiliar diferente:

function augment(obj, name) {
    return function (res) { var r = Object.assign({}, obj); r[name] = res; return r; };
}

function getExample() {
    return promiseA(…).then(function(resultA) {
        // some processing
        return promiseB(…).then(augment({resultA}, "resultB"));
    }).then(function(obj) {
        // more processing
        return // something using both obj.resultA and obj.resultB
    });
}

Si bien este patrón garantiza una cadena plana y los objetos de estado explícitos pueden mejorar la claridad, se volverá tedioso para una cadena larga. Especialmente cuando solo necesita el estado esporádicamente, aún debe pasarlo en cada paso. Con esta interfaz fija, las devoluciones de llamada únicas en la cadena están estrechamente acopladas y son inflexibles al cambio. Hace que la factorización de pasos individuales sea más difícil y las devoluciones de llamada no se pueden proporcionar directamente desde otros módulos; siempre deben incluirse en un código repetitivo que se preocupe por el estado. Las funciones de ayuda abstractas como las anteriores pueden aliviar un poco el dolor, pero siempre estarán presentes.

35
Bergi 2015-02-01 00:43.

Estado contextual mutable

La solución trivial (pero poco elegante y bastante propensa a errores) es simplemente usar variables de mayor alcance (a las que tienen acceso todas las devoluciones de llamada en la cadena) y escribir valores de resultado en ellas cuando las obtenga:

function getExample() {
    var resultA;
    return promiseA(…).then(function(_resultA) {
        resultA = _resultA;
        // some processing
        return promiseB(…);
    }).then(function(resultB) {
        // more processing
        return // something using both resultA and resultB
    });
}

En lugar de muchas variables, también se puede usar un objeto (inicialmente vacío), en el que los resultados se almacenan como propiedades creadas dinámicamente.

Esta solución tiene varios inconvenientes:

  • El estado mutable es feo y las variables globales son malas .
  • Este patrón no funciona a través de los límites de las funciones, modularizar las funciones es más difícil ya que sus declaraciones no deben salir del ámbito compartido
  • El alcance de las variables no impide acceder a ellas antes de que se inicialicen. Esto es especialmente probable para construcciones de promesas complejas (bucles, ramificaciones, excepciones) donde pueden ocurrir condiciones de carrera. Pasar el estado explícitamente, un diseño declarativo que promete alentar, fuerza un estilo de codificación más limpio que puede prevenir esto.
  • Uno debe elegir correctamente el alcance de esas variables compartidas. Debe ser local a la función ejecutada para evitar condiciones de carrera entre múltiples invocaciones paralelas, como sería el caso si, por ejemplo, el estado se almacenara en una instancia.

La biblioteca Bluebird fomenta el uso de un objeto que se transmite, utilizando su bind()método para asignar un objeto de contexto a una cadena de promesa. Será accesible desde cada función de devolución de llamada a través de la thispalabra clave inutilizable . Si bien las propiedades de los objetos son más propensas a errores tipográficos no detectados que las variables, el patrón es bastante inteligente:

function getExample() {
    return promiseA(…)
    .bind({}) // Bluebird only!
    .then(function(resultA) {
        this.resultA = resultA;
        // some processing
        return promiseB(…);
    }).then(function(resultB) {
        // more processing
        return // something using both this.resultA and resultB
    }).bind(); // don't forget to unbind the object if you don't want the
               // caller to access it
}

Este enfoque se puede simular fácilmente en bibliotecas de promesas que no admiten .bind (aunque de una manera algo más detallada y no se puede usar en una expresión):

function getExample() {
    var ctx = {};
    return promiseA(…)
    .then(function(resultA) {
        this.resultA = resultA;
        // some processing
        return promiseB(…);
    }.bind(ctx)).then(function(resultB) {
        // more processing
        return // something using both this.resultA and resultB
    }.bind(ctx));
}
16
Jay 2017-03-25 10:08.

Un giro menos severo sobre el "estado contextual mutable"

El uso de un objeto de ámbito local para recopilar los resultados intermedios en una cadena de promesas es un enfoque razonable para la pregunta que planteó. Considere el siguiente fragmento:

function getExample(){
    //locally scoped
    const results = {};
    return promiseA(paramsA).then(function(resultA){
        results.a = resultA;
        return promiseB(paramsB);
    }).then(function(resultB){
        results.b = resultB;
        return promiseC(paramsC);
    }).then(function(resultC){
        //Resolve with composite of all promises
        return Promise.resolve(results.a + results.b + resultC);
    }).catch(function(error){
        return Promise.reject(error);
    });
}
  • Las variables globales son malas, por lo que esta solución utiliza una variable de ámbito local que no causa ningún daño. Solo es accesible dentro de la función.
  • El estado mutable es feo, pero esto no cambia el estado de una manera fea. El estado feo mutable se refiere tradicionalmente a modificar el estado de los argumentos de la función o las variables globales, pero este enfoque simplemente modifica el estado de una variable de ámbito local que existe con el único propósito de agregar resultados de promesa ... una vez que la promesa se resuelve.
  • No se impide que las promesas intermedias accedan al estado del objeto de resultados, pero esto no introduce un escenario aterrador en el que una de las promesas en la cadena se vuelva deshonesta y sabotee sus resultados. La responsabilidad de establecer los valores en cada paso de la promesa se limita a esta función y el resultado general será correcto o incorrecto ... no será un error que surgirá años más tarde en producción (a menos que tenga la intención de hacerlo). !)
  • Esto no introduce un escenario de condición de carrera que surgiría de la invocación paralela porque se crea una nueva instancia de la variable de resultados para cada invocación de la función getExample.
8
Anthony 2017-01-22 12:14.

El nodo 7.4 ahora admite llamadas asíncronas / en espera con la bandera de armonía.

Prueba esto:

async function getExample(){

  let response = await returnPromise();

  let response2 = await returnPromise2();

  console.log(response, response2)

}

getExample()

y ejecuta el archivo con:

node --harmony-async-await getExample.js

¡Tan simple como puede ser!

8
yzfdjzwl 2017-07-25 20:34.

En estos días, también he conocido a algunas preguntas como tú. Por fin, encuentro una buena solución con la pregunta, es simple y buena de leer. Espero que esto pueda ayudarte.

Según cómo-encadenar-las-promesas-de-JavaScript

ok, veamos el código:

const firstPromise = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('first promise is completed');
            resolve({data: '123'});
        }, 2000);
    });
};

const secondPromise = (someStuff) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('second promise is completed');
            resolve({newData: `${someStuff.data} some more data`});
        }, 2000);
    });
};

const thirdPromise = (someStuff) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('third promise is completed');
            resolve({result: someStuff});
        }, 2000);
    });
};

firstPromise()
    .then(secondPromise)
    .then(thirdPromise)
    .then(data => {
        console.log(data);
    });
6
Anthony 2015-11-21 09:59.

Otra respuesta, usando la babel-nodeversión <6

Utilizando async - await

npm install -g [email protected]

example.js:

async function getExample(){

  let response = await returnPromise();

  let response2 = await returnPromise2();

  console.log(response, response2)

}

getExample()

Entonces, ¡corre babel-node example.jsy listo!

2
Anthony 2015-08-12 08:35.

No voy a usar este patrón en mi propio código ya que no soy un gran fanático del uso de variables globales. Sin embargo, en caso de apuro, funcionará.

El usuario es un modelo Mongoose prometido.

var globalVar = '';

User.findAsync({}).then(function(users){
  globalVar = users;
}).then(function(){
  console.log(globalVar);
});
2
amaksr 2017-06-10 14:56.

Otra respuesta, usando el ejecutor secuencial nsynjs :

function getExample(){

  var response1 = returnPromise1().data;

  // promise1 is resolved at this point, '.data' has the result from resolve(result)

  var response2 = returnPromise2().data;

  // promise2 is resolved at this point, '.data' has the result from resolve(result)

  console.log(response, response2);

}

nynjs.run(getExample,{},function(){
    console.log('all done');
})

Actualización: ejemplo de trabajo agregado

function synchronousCode() {
     var urls=[
         "https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js",
         "https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js",
         "https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"
     ];
     for(var i=0; i<urls.length; i++) {
         var len=window.fetch(urls[i]).data.text().data.length;
         //             ^                   ^
         //             |                   +- 2-nd promise result
         //             |                      assigned to 'data'
         //             |
         //             +-- 1-st promise result assigned to 'data'
         //
         console.log('URL #'+i+' : '+urls[i]+", length: "+len);
     }
}

nsynjs.run(synchronousCode,{},function(){
    console.log('all done');
})
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>

1
alphakevin 2016-06-12 20:33.

Al usar bluebird, puede usar el .bindmétodo para compartir variables en la cadena de promesa:

somethingAsync().bind({})
.spread(function (aValue, bValue) {
    this.aValue = aValue;
    this.bValue = bValue;
    return somethingElseAsync(aValue, bValue);
})
.then(function (cValue) {
    return this.aValue + this.bValue + cValue;
});

Consulte este enlace para obtener más información:

http://bluebirdjs.com/docs/api/promise.bind.html

1
Minh Giang 2017-03-03 23:45.
function getExample() {
    var retA, retB;
    return promiseA(…).then(function(resultA) {
        retA = resultA;
        // Some processing
        return promiseB(…);
    }).then(function(resultB) {
        // More processing
        //retA is value of promiseA
        return // How do I gain access to resultA here?
    });
}

manera fácil: D

1
Vishu 2017-08-30 00:34.

Creo que puedes usar el hash de RSVP.

Algo parecido a lo siguiente:

    const mainPromise = () => {
        const promise1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log('first promise is completed');
                resolve({data: '123'});
            }, 2000);
        });

        const promise2 = new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log('second promise is completed');
                resolve({data: '456'});
            }, 2000);
        });

        return new RSVP.hash({
              prom1: promise1,
              prom2: promise2
          });

    };


   mainPromise()
    .then(data => {
        console.log(data.prom1);
        console.log(data.prom2);
    });
0
David Spector 2019-08-28 10:17.

Solución:

Puede poner valores intermedios en el alcance en cualquier función posterior 'luego' explícitamente, utilizando 'bind'. Es una buena solución que no requiere cambiar la forma en que funcionan las Promesas, y solo requiere una línea o dos de código para propagar los valores al igual que los errores ya se propagan.

Aquí tienes un ejemplo completo:

// Get info asynchronously from a server
function pGetServerInfo()
    {
    // then value: "server info"
    } // pGetServerInfo

// Write into a file asynchronously
function pWriteFile(path,string)
    {
    // no then value
    } // pWriteFile

// The heart of the solution: Write formatted info into a log file asynchronously,
// using the pGetServerInfo and pWriteFile operations
function pLogInfo(localInfo)
    {
    var scope={localInfo:localInfo}; // Create an explicit scope object
    var thenFunc=p2.bind(scope); // Create a temporary function with this scope
    return (pGetServerInfo().then(thenFunc)); // Do the next 'then' in the chain
    } // pLogInfo

// Scope of this 'then' function is {localInfo:localInfo}
function p2(serverInfo)
    {
    // Do the final 'then' in the chain: Writes "local info, server info"
    return pWriteFile('log',this.localInfo+','+serverInfo);
    } // p2

Esta solución se puede invocar de la siguiente manera:

pLogInfo("local info").then().catch(err);

(Nota: se ha probado una versión más compleja y completa de esta solución, pero no esta versión de ejemplo, por lo que podría tener un error).

Related questions

MORE COOL STUFF

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

¿Caduca el repelente de insectos?

¿Caduca el repelente de insectos?

¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?

Estados Unidos podría evitarse el horror del nuevo gran horneado británico

Estados Unidos podría evitarse el horror del nuevo gran horneado británico

Si este tráiler de pesadilla de la temporada más reciente de Great British Bake Off te asustó y te hizo no volver a ver el programa, es posible que tengas suerte: PBS no ha decidido si se transmitirá o no la última temporada en los Estados Unidos. actualización, para aquellos que no siguen sin aliento este tipo de drama de nicho: el presentador Paul Hollywood y la hermosa carpa llena de batidoras de colores pastel y cuadros se trasladaron de la BBC al Canal 4; Mary Berry, Sue Perkins y Mel Giedroyc renunciaron.

Atún como Oh, Hello llega a Netflix

Atún como Oh, Hello llega a Netflix

Foto: Netflix Oh, Hello On Broadway (Netflix): Después de llegar a Broadway el año pasado, los dos locos del Upper West Side interpretados por John Mulaney y Nick Kroll finalmente llegaron a Netflix. El especial consta del espectáculo en el escenario, algunos momentos entre bastidores y un invitado muy especial de “Too Much Tuna”.

Actualice a un Sonicare por tan solo $ 30

Actualice a un Sonicare por tan solo $ 30

¿Quiere probar un cepillo de dientes Sonicare sin gastar mucho dinero en uno de sus modelos favoritos de gama alta? Puede comprar un kit de la Serie 2 o Serie 3 por tan solo $ 30 hoy en Amazon. Haga clic aquí para ver la lista completa de modelos elegibles y tenga en cuenta que se descontarán $ 10 adicionales en su carrito.

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.

India me está pateando el culo

India me está pateando el culo

Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

¿Merrick Garland le ha fallado a Estados Unidos?

Es más de la mitad de la presidencia de Biden. ¿Qué está esperando Merrick Garland?

¿Merrick Garland le ha fallado a Estados Unidos?

Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.

Language