¿Hay algún problema con el uso de async
/ await
en un forEach
bucle? Estoy tratando de recorrer una matriz de archivos y await
el contenido de cada archivo.
import fs from 'fs-promise'
async function printFiles () {
const files = await getFilePaths() // Assume this works fine
files.forEach(async (file) => {
const contents = await fs.readFile(file, 'utf8')
console.log(contents)
})
}
printFiles()
Este código funciona, pero ¿podría salir mal algo con esto? Alguien me dijo que se supone que no debes usar async
/ await
en una función de orden superior como esta, así que solo quería preguntar si había algún problema con esto.
Seguro que el código funciona, pero estoy bastante seguro de que no hace lo que esperas que haga. Simplemente dispara múltiples llamadas asincrónicas, pero la printFiles
función regresa inmediatamente después de eso.
Si desea leer los archivos en secuencia, no puede usarlosforEach
. Simplemente use un for … of
bucle moderno en su lugar, en el que await
funcionará como se esperaba:
async function printFiles () {
const files = await getFilePaths();
for (const file of files) {
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
}
}
Si desea leer los archivos en paralelo, no puede usarlosforEach
. Cada una de las async
llamadas a la función de devolución de llamada devuelve una promesa, pero las está desechando en lugar de esperarlas. Solo use map
en su lugar, y puede esperar la variedad de promesas que obtendrá con Promise.all
:
async function printFiles () {
const files = await getFilePaths();
await Promise.all(files.map(async (file) => {
const contents = await fs.readFile(file, 'utf8')
console.log(contents)
}));
}
Con ES2018, puede simplificar enormemente todas las respuestas anteriores a:
async function printFiles () {
const files = await getFilePaths()
for await (const contents of fs.readFile(file, 'utf8')) {
console.log(contents)
}
}
Ver especificaciones: propuesta-iteración asíncrona
2018-09-10: esta respuesta ha recibido mucha atención recientemente, consulte la publicación del blog de Axel Rauschmayer para obtener más información sobre la iteración asincrónica: ES2018: iteración asincrónica
En lugar de Promise.all
en conjunto con Array.prototype.map
(que no garantiza el orden en el que Promise
se resuelven los s), utilizo Array.prototype.reduce
, comenzando con un resuelto Promise
:
async function printFiles () {
const files = await getFilePaths();
await files.reduce(async (promise, file) => {
// This line will wait for the last async function to finish.
// The first iteration uses an already resolved Promise
// so, it will immediately continue.
await promise;
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
}, Promise.resolve());
}
El módulo p- iteration en npm implementa los métodos de iteración Array para que se puedan usar de una manera muy sencilla con async / await.
Un ejemplo con tu caso:
const { forEach } = require('p-iteration');
const fs = require('fs-promise');
(async function printFiles () {
const files = await getFilePaths();
await forEach(files, async (file) => {
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
});
})();
A continuación se muestran algunos forEachAsync
prototipos. Tenga en cuenta que los necesitará await
:
Array.prototype.forEachAsync = async function (fn) {
for (let t of this) { await fn(t) }
}
Array.prototype.forEachAsyncParallel = async function (fn) {
await Promise.all(this.map(fn));
}
Tenga en cuenta que si bien puede incluir esto en su propio código, no debe incluirlo en las bibliotecas que distribuye a otros (para evitar contaminar sus globales).
Además de la respuesta de @ Bergi , me gustaría ofrecer una tercera alternativa. Es muy similar al segundo ejemplo de @ Bergi, pero en lugar de esperar cada uno readFile
individualmente, creas una serie de promesas, cada una de las cuales esperas al final.
import fs from 'fs-promise';
async function printFiles () {
const files = await getFilePaths();
const promises = files.map((file) => fs.readFile(file, 'utf8'))
const contents = await Promise.all(promises)
contents.forEach(console.log);
}
Tenga en cuenta que la función pasada a .map()
no tiene por qué ser así async
, ya que fs.readFile
devuelve un objeto Promise de todos modos. Por promises
lo tanto, es una matriz de objetos Promise, a los que se puede enviar Promise.all()
.
En la respuesta de @ Bergi, la consola puede registrar el contenido del archivo en el orden en que se lee. Por ejemplo, si un archivo realmente pequeño termina de leerse antes que un archivo realmente grande, se registrará primero, incluso si el archivo pequeño viene después del archivo grande en la files
matriz. Sin embargo, en mi método anterior, tiene la garantía de que la consola registrará los archivos en el mismo orden que la matriz proporcionada.
La solución de Bergi funciona bien cuando fs
se basa en promesas. Puede usar bluebird
, fs-extra
o fs-promise
para esto.
Sin embargo, la solución para la fs
biblioteca nativa del nodo es la siguiente:
const result = await Promise.all(filePaths
.map( async filePath => {
const fileContents = await getAssetFromCache(filePath, async function() {
// 1. Wrap with Promise
// 2. Return the result of the Promise
return await new Promise((res, rej) => {
fs.readFile(filePath, 'utf8', function(err, data) {
if (data) {
res(data);
}
});
});
});
return fileContents;
}));
Nota:
require('fs')
obligatoriamente toma la función como tercer argumento, de lo contrario arroja un error:
TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
Ambas soluciones funcionan, sin embargo, Antonio hace el trabajo con menos código, así es como me ayudó a resolver los datos de mi base de datos, de varias referencias secundarias diferentes y luego empujarlas todas en una matriz y resolverlas en una promesa después de todo es hecho:
Promise.all(PacksList.map((pack)=>{
return fireBaseRef.child(pack.folderPath).once('value',(snap)=>{
snap.forEach( childSnap => {
const file = childSnap.val()
file.id = childSnap.key;
allItems.push( file )
})
})
})).then(()=>store.dispatch( actions.allMockupItems(allItems)))
Es bastante sencillo colocar un par de métodos en un archivo que manejará datos asincrónicos en un orden serializado y le dará un sabor más convencional a su código. Por ejemplo:
module.exports = function () {
var self = this;
this.each = async (items, fn) => {
if (items && items.length) {
await Promise.all(
items.map(async (item) => {
await fn(item);
}));
}
};
this.reduce = async (items, fn, initialValue) => {
await self.each(
items, async (item) => {
initialValue = await fn(initialValue, item);
});
return initialValue;
};
};
ahora, asumiendo que está guardado en './myAsync.js', puede hacer algo similar a lo siguiente en un archivo adyacente:
...
/* your server setup here */
...
var MyAsync = require('./myAsync');
var Cat = require('./models/Cat');
var Doje = require('./models/Doje');
var example = async () => {
var myAsync = new MyAsync();
var doje = await Doje.findOne({ name: 'Doje', noises: [] }).save();
var cleanParams = [];
// FOR EACH EXAMPLE
await myAsync.each(['bork', 'concern', 'heck'],
async (elem) => {
if (elem !== 'heck') {
await doje.update({ $push: { 'noises': elem }});
}
});
var cat = await Cat.findOne({ name: 'Nyan' });
// REDUCE EXAMPLE
var friendsOfNyanCat = await myAsync.reduce(cat.friends,
async (catArray, friendId) => {
var friend = await Friend.findById(friendId);
if (friend.name !== 'Long cat') {
catArray.push(friend.name);
}
}, []);
// Assuming Long Cat was a friend of Nyan Cat...
assert(friendsOfNyanCat.length === (cat.friends.length - 1));
}
Esta solución también está optimizada para la memoria, por lo que puede ejecutarla en 10,000 elementos de datos y solicitudes. Algunas de las otras soluciones aquí bloquean el servidor en grandes conjuntos de datos.
En TypeScript:
export async function asyncForEach<T>(array: Array<T>, callback: (item: T, index: number) => void) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index);
}
}
¿Cómo utilizar?
await asyncForEach(receipts, async (eachItem) => {
await ...
})
Una advertencia importante es: el await + for .. of
método y la forEach + async
forma en realidad tienen un efecto diferente.
Tener await
dentro un for
bucle real asegurará que todas las llamadas asíncronas se ejecuten una por una. Y el forEach + async
camino disparará todas las promesas al mismo tiempo, lo que es más rápido pero a veces abrumador ( si realiza alguna consulta de base de datos o visita algunos servicios web con restricciones de volumen y no desea disparar 100.000 llamadas a la vez).
También puede usar reduce + promise
(menos elegante) si no lo usa async/await
y desea asegurarse de que los archivos se lean uno tras otro .
files.reduce((lastPromise, file) =>
lastPromise.then(() =>
fs.readFile(file, 'utf8')
), Promise.resolve()
)
O puede crear un forEachAsync para ayudar, pero básicamente usar el mismo para el bucle subyacente.
Array.prototype.forEachAsync = async function(cb){
for(let x of this){
await cb(x);
}
}
Solo agregando a la respuesta original
async function printFiles() {
const files = await getFilePaths();
const fileReadPromises = [];
const readAndLogFile = async filePath => {
const contents = await fs.readFile(file, "utf8");
console.log(contents);
return contents;
};
files.forEach(file => {
fileReadPromises.push(readAndLogFile(file));
});
await Promise.all(fileReadPromises);
}
async function printFiles() {
const files = await getFilePaths();
for (let i = 0; i < files.length; i++) {
const file = files[i];
const contents = await fs.readFile(file, "utf8");
console.log(contents);
}
}
Como la respuesta de @ Bergi, pero con una diferencia.
Promise.all
rechaza todas las promesas si una es rechazada.
Entonces, use una recursividad.
const readFilesQueue = async (files, index = 0) {
const contents = await fs.readFile(files[index], 'utf8')
console.log(contents)
return files.length <= index
? readFilesQueue(files, ++index)
: files
}
const printFiles async = () => {
const files = await getFilePaths();
const printContents = await readFilesQueue(files)
return printContents
}
printFiles()
PD
readFilesQueue
está fuera de la printFiles
causa del efecto secundario * introducido por console.log
, es mejor burlarse, probar o espiar, por lo que no es bueno tener una función que devuelva el contenido (nota al margen).
Por lo tanto, el código puede diseñarse simplemente por eso: tres funciones separadas que son "puras" ** y no introducen efectos secundarios, procesan la lista completa y pueden modificarse fácilmente para manejar casos fallidos.
const files = await getFilesPath()
const printFile = async (file) => {
const content = await fs.readFile(file, 'utf8')
console.log(content)
}
const readFiles = async = (files, index = 0) => {
await printFile(files[index])
return files.lengh <= index
? readFiles(files, ++index)
: files
}
readFiles(files)
Edición futura / estado actual
Node admite la espera de nivel superior (esto aún no tiene un complemento, no lo tendrá y se puede habilitar a través de indicadores de armonía), es genial pero no resuelve un problema (estratégicamente trabajo solo en versiones LTS). ¿Cómo conseguir los archivos?
Usando composición. Dado el código, me causa la sensación de que este está dentro de un módulo, por lo que debería tener una función para hacerlo. De lo contrario, debe usar un IIFE para envolver el código de función en una función asíncrona creando un módulo simple que lo haga todo por usted, o puede seguir la forma correcta, hay composición.
// more complex version with IIFE to a single module
(async (files) => readFiles(await files())(getFilesPath)
Tenga en cuenta que el nombre de la variable cambia debido a la semántica. Pasas un functor (una función que puede ser invocada por otra función) y recibes un puntero en la memoria que contiene el bloque inicial de lógica de la aplicación.
Pero, ¿no es un módulo y necesitas exportar la lógica?
Envuelva las funciones en una función asincrónica.
export const readFilesQueue = async () => {
// ... to code goes here
}
O cambiar los nombres de las variables, lo que sea ...
*
por efecto secundario menans cualquier efecto colacteral de la aplicación que pueda cambiar el estado / comportamiento o introducir errores en la aplicación, como IO.
**
por "puro", está en apóstrofo ya que las funciones no son puras y el código puede converger a una versión pura, cuando no hay salida de consola, solo manipulaciones de datos.
Aparte de esto, para ser puro, necesitará trabajar con mónadas que manejen el efecto secundario, que sean propensas a errores, y traten ese error por separado de la aplicación.
Usando Task, futurize y una lista transitable, simplemente puede hacer
async function printFiles() {
const files = await getFiles();
List(files).traverse( Task.of, f => readFile( f, 'utf-8'))
.fork( console.error, console.log)
}
Así es como lo configuraría
import fs from 'fs';
import { futurize } from 'futurize';
import Task from 'data.task';
import { List } from 'immutable-ext';
const future = futurizeP(Task)
const readFile = future(fs.readFile)
Otra forma de haber estructurado el código deseado sería
const printFiles = files =>
List(files).traverse( Task.of, fn => readFile( fn, 'utf-8'))
.fork( console.error, console.log)
O quizás incluso más funcionalmente orientado
// 90% of encodings are utf-8, making that use case super easy is prudent
// handy-library.js
export const readFile = f =>
future(fs.readFile)( f, 'utf-8' )
export const arrayToTaskList = list => taskFn =>
List(files).traverse( Task.of, taskFn )
export const readFiles = files =>
arrayToTaskList( files, readFile )
export const printFiles = files =>
readFiles(files).fork( console.error, console.log)
Luego de la función padre
async function main() {
/* awesome code with side-effects before */
printFiles( await getFiles() );
/* awesome code with side-effects after */
}
Si realmente desea más flexibilidad en la codificación, puede hacer esto (por diversión, estoy usando el operador Pipe Forward propuesto )
import { curry, flip } from 'ramda'
export const readFile = fs.readFile
|> future,
|> curry,
|> flip
export const readFileUtf8 = readFile('utf-8')
PD: no probé este código en la consola, podría tener algunos errores tipográficos ... "¡estilo libre directo, desde la parte superior del domo!" como dirían los niños de los 90. :-pag
Actualmente, la propiedad del prototipo Array.forEach no admite operaciones asincrónicas, pero podemos crear nuestro propio poly-fill para satisfacer nuestras necesidades.
// Example of asyncForEach Array poly-fill for NodeJs
// file: asyncForEach.js
// Define asynForEach function
async function asyncForEach(iteratorFunction){
let indexer = 0
for(let data of this){
await iteratorFunction(data, indexer)
indexer++
}
}
// Append it as an Array prototype property
Array.prototype.asyncForEach = asyncForEach
module.exports = {Array}
¡Y eso es! Ahora tiene un método async forEach disponible en cualquier matriz que se defina después de estas para operaciones.
Vamos a probarlo ...
// Nodejs style
// file: someOtherFile.js
const readline = require('readline')
Array = require('./asyncForEach').Array
const log = console.log
// Create a stream interface
function createReader(options={prompt: '>'}){
return readline.createInterface({
input: process.stdin
,output: process.stdout
,prompt: options.prompt !== undefined ? options.prompt : '>'
})
}
// Create a cli stream reader
async function getUserIn(question, options={prompt:'>'}){
log(question)
let reader = createReader(options)
return new Promise((res)=>{
reader.on('line', (answer)=>{
process.stdout.cursorTo(0, 0)
process.stdout.clearScreenDown()
reader.close()
res(answer)
})
})
}
let questions = [
`What's your name`
,`What's your favorite programming language`
,`What's your favorite async function`
]
let responses = {}
async function getResponses(){
// Notice we have to prepend await before calling the async Array function
// in order for it to function as expected
await questions.asyncForEach(async function(question, index){
let answer = await getUserIn(question)
responses[question] = answer
})
}
async function main(){
await getResponses()
log(responses)
}
main()
// Should prompt user for an answer to each question and then
// log each question and answer as an object to the terminal
Podríamos hacer lo mismo para algunas de las otras funciones de matriz como map ...
async function asyncMap(iteratorFunction){
let newMap = []
let indexer = 0
for(let data of this){
newMap[indexer] = await iteratorFunction(data, indexer, this)
indexer++
}
return newMap
}
Array.prototype.asyncMap = asyncMap
... y así :)
Algunas cosas a tener en cuenta:
Array.prototype.<yourAsyncFunc> = <yourAsyncFunc>
no tendrá esta función disponibleHoy encontré múltiples soluciones para esto. Ejecutando las funciones asíncronas en espera en el bucle forEach. Construyendo el envoltorio podemos hacer que esto suceda.
En el enlace aquí se proporciona una explicación más detallada sobre cómo funciona internamente, para el forEach nativo y por qué no puede realizar una llamada de función asíncrona y otros detalles sobre los diversos métodos.
Las múltiples formas a través de las cuales se puede hacer y son las siguientes,
Método 1: usando la envoltura.
await (()=>{
return new Promise((resolve,reject)=>{
items.forEach(async (item,index)=>{
try{
await someAPICall();
} catch(e) {
console.log(e)
}
count++;
if(index === items.length-1){
resolve('Done')
}
});
});
})();
Método 2: usar lo mismo que una función genérica de Array.prototype
Array.prototype.forEachAsync.js
if(!Array.prototype.forEachAsync) {
Array.prototype.forEachAsync = function (fn){
return new Promise((resolve,reject)=>{
this.forEach(async(item,index,array)=>{
await fn(item,index,array);
if(index === array.length-1){
resolve('done');
}
})
});
};
}
Uso:
require('./Array.prototype.forEachAsync');
let count = 0;
let hello = async (items) => {
// Method 1 - Using the Array.prototype.forEach
await items.forEachAsync(async () => {
try{
await someAPICall();
} catch(e) {
console.log(e)
}
count++;
});
console.log("count = " + count);
}
someAPICall = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("done") // or reject('error')
}, 100);
})
}
hello(['', '', '', '']); // hello([]) empty array is also be handled by default
Método 3:
Usando Promise.all
await Promise.all(items.map(async (item) => {
await someAPICall();
count++;
}));
console.log("count = " + count);
Método 4: bucle for tradicional o bucle for moderno
// Method 4 - using for loop directly
// 1. Using the modern for(.. in..) loop
for(item in items){
await someAPICall();
count++;
}
//2. Using the traditional for loop
for(let i=0;i<items.length;i++){
await someAPICall();
count++;
}
console.log("count = " + count);
Puede usar Array.prototype.forEach
, pero async / await no es tan compatible. Esto se debe a que la promesa devuelta de una devolución de llamada asincrónica espera resolverse, pero Array.prototype.forEach
no resuelve ninguna promesa de la ejecución de su devolución de llamada. Entonces, puede usar forEach, pero tendrá que manejar la resolución de la promesa usted mismo.
Aquí hay una forma de leer e imprimir cada archivo en serie usando Array.prototype.forEach
async function printFilesInSeries () {
const files = await getFilePaths()
let promiseChain = Promise.resolve()
files.forEach((file) => {
promiseChain = promiseChain.then(() => {
fs.readFile(file, 'utf8').then((contents) => {
console.log(contents)
})
})
})
await promiseChain
}
Aquí hay una forma (que todavía se usa Array.prototype.forEach
) de imprimir el contenido de los archivos en paralelo
async function printFilesInParallel () {
const files = await getFilePaths()
const promises = []
files.forEach((file) => {
promises.push(
fs.readFile(file, 'utf8').then((contents) => {
console.log(contents)
})
)
})
await Promise.all(promises)
}
Para ver cómo puede salir mal, imprima console.log al final del método.
Cosas que pueden salir mal en general:
Estos no siempre son incorrectos, pero con frecuencia se encuentran en casos de uso estándar.
Generalmente, el uso de forEach dará como resultado todos menos el último. Llamará a cada función sin esperar la función, lo que significa que le dice a todas las funciones que comiencen y luego finalice sin esperar a que terminen las funciones.
import fs from 'fs-promise'
async function printFiles () {
const files = (await getFilePaths()).map(file => fs.readFile(file, 'utf8'))
for(const file of files)
console.log(await file)
}
printFiles()
Este es un ejemplo en JS nativo que preservará el orden, evitará que la función regrese prematuramente y, en teoría, conservará un rendimiento óptimo.
Esta voluntad:
Con esta solución, el primer archivo se mostrará tan pronto como esté disponible sin tener que esperar a que los demás estén disponibles primero.
También cargará todos los archivos al mismo tiempo en lugar de tener que esperar a que termine el primero antes de que se pueda iniciar la lectura del segundo archivo.
El único inconveniente de esto y la versión original es que si se inician varias lecturas a la vez, es más difícil manejar los errores debido a que hay más errores que pueden ocurrir a la vez.
Con las versiones que leen un archivo a la vez, luego se detendrá en caso de falla sin perder tiempo tratando de leer más archivos. Incluso con un sistema de cancelación elaborado, puede ser difícil evitar que falle en el primer archivo, pero también leer la mayoría de los otros archivos.
El rendimiento no siempre es predecible. Si bien muchos sistemas serán más rápidos con lecturas de archivos paralelas, algunos preferirán la secuencial. Algunos son dinámicos y pueden cambiar bajo carga, las optimizaciones que ofrecen latencia no siempre producen un buen rendimiento bajo una fuerte contención.
Tampoco hay manejo de errores en ese ejemplo. Si algo requiere que se muestren correctamente o no se muestren, no lo hará.
Se recomienda experimentar en profundidad con console.log en cada etapa y soluciones de lectura de archivos falsos (en su lugar, retraso aleatorio). Aunque muchas soluciones parecen hacer lo mismo en casos simples, todas tienen diferencias sutiles que requieren un escrutinio adicional para exprimirlas.
Utilice este simulacro para ayudar a diferenciar las soluciones:
(async () => {
const start = +new Date();
const mock = () => {
return {
fs: {readFile: file => new Promise((resolve, reject) => {
// Instead of this just make three files and try each timing arrangement.
// IE, all same, [100, 200, 300], [300, 200, 100], [100, 300, 200], etc.
const time = Math.round(100 + Math.random() * 4900);
console.log(`Read of ${file} started at ${new Date() - start} and will take ${time}ms.`)
setTimeout(() => {
// Bonus material here if random reject instead.
console.log(`Read of ${file} finished, resolving promise at ${new Date() - start}.`);
resolve(file);
}, time);
})},
console: {log: file => console.log(`Console Log of ${file} finished at ${new Date() - start}.`)},
getFilePaths: () => ['A', 'B', 'C', 'D', 'E']
};
};
const printFiles = (({fs, console, getFilePaths}) => {
return async function() {
const files = (await getFilePaths()).map(file => fs.readFile(file, 'utf8'));
for(const file of files)
console.log(await file);
};
})(mock());
console.log(`Running at ${new Date() - start}`);
await printFiles();
console.log(`Finished running at ${new Date() - start}`);
})();
const AsyncAF = require('async-af');
const fs = require('fs-promise');
function printFiles() {
// since AsyncAF accepts promises or non-promises, there's no need to await here
const files = getFilePaths();
AsyncAF(files).forEach(async file => {
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
});
}
printFiles();
Alternativamente, async-af
tiene un método estático (log / logAF) que registra los resultados de las promesas:
const AsyncAF = require('async-af');
const fs = require('fs-promise');
function printFiles() {
const files = getFilePaths();
AsyncAF(files).forEach(file => {
AsyncAF.log(fs.readFile(file, 'utf8'));
});
}
printFiles();
Sin embargo, la principal ventaja de la biblioteca es que puede encadenar métodos asincrónicos para hacer algo como:
const aaf = require('async-af');
const fs = require('fs-promise');
const printFiles = () => aaf(getFilePaths())
.map(file => fs.readFile(file, 'utf8'))
.forEach(file => aaf.log(file));
printFiles();
La estrella de 'Gran Hermano', Claire Rehfuss, advierte a los fanáticos que no confíen en las cuentas de los spoilers.
Kristen Stewart una vez le dio un fuerte puñetazo a su coprotagonista de 'Blancanieves', Chris Hemsworth, que fue un ataque que el actor no vio venir.
En una entrevista con la revista GQ, Jin de BTS reveló que una parte de la canción de BTS y Coldplay 'My Universe' no 'llegó al corte final'.
'Scream' establece un regreso sangriento que provoca algunas nuevas direcciones, pero la nueva ola de asesinatos de Ghostface no es tan profunda como debería.
¡Nuestro mini crucigrama actualizado semanalmente combina nuestras lecturas favoritas de HowStuffWorks con pistas inteligentes!
Lavar la ropa ya es bastante malo sin tener que preocuparse por elegir el detergente adecuado. Entonces, ¿cuál es mejor? ó acaso importa?
Las familias Fugate y Combs en la zona rural de Kentucky perdieron la lotería genética, y ambos compartían un rasgo recesivo raro que hacía que su piel se viera azul cuando se casaron. ¿Cuál fue la causa de esto? ¿Y qué pasó con las familias?
Se están criando dos polluelos sin padre en un programa para salvar al cóndor de California de la extinción. ¿Cómo son posibles estos nacimientos 'vírgenes'?
La estrella de Vanderpump Rules, Katie Maloney-Schwartz, habló sobre el progreso que ha logrado en su viaje de amor propio en una publicación honesta y sincera en Instagram el jueves.
Jessica Alba compartió un encantador video en su Instagram que la muestra a ella y a sus hijos acurrucándose y jugando con los dos perros llamados Dolly y Lucy.
"Fue una situación de amor a primera vista", le dice una fuente a PEOPLE sobre Megan Fox y Machine Gun Kelly, quienes se comprometieron el fin de semana pasado durante unas vacaciones en Puerto Rico.
Según la policía, Devonne Marsh supuestamente cubrió a su novia, que no ha sido identificada, con líquido para encendedores y encendió las llamas.
Los empresarios no son personas promedio, son una raza especial. Sus ciertos rasgos de personalidad los ayudan a liderar equipos, administrar negocios y construir imperios.
Introducción Este proyecto de Customer Journey Map es la segunda y última sección que formará el bloque de análisis de mi estudio de caso de UX. El proceso ha sido guiado y desarrollado durante mis estudios en el UX Design Institute.
La naturaleza pública e inmutable de Bitcoin requiere el regreso de los nodos mixtos para lograr una verdadera privacidad a nivel de red. Harry Halpin y Ania Piotrowska 20 de enero de 2022 Muchos concibieron originalmente Bitcoin como un dinero digital anónimo, ya que todas las transacciones se realizan como transferencias entre pares entre direcciones de billetera que actúan como seudónimos.
Este mundo está lleno de posibilidades y probabilidades. A veces las cosas salen a tu manera, a veces no.