[ES6] Promesa de aprendizaje de Ruan Yifeng ES6 (1)

1. Significado

la promesa esprogramación asíncronauna solución para

1. Concepto

En pocas palabras, es un contenedor que contiene los resultados de los eventos (generalmente una operación asincrónica) que terminarán en el futuro. Sintácticamente, Promiseun objeto del que se pueden obtener mensajes para operaciones asíncronas. PromiseProporcione un unificado API, todo tipo de operaciones asincrónicas se pueden procesar de la misma manera.

programación asíncrona: operación de archivo fs, operación de base de datos, Ajax, temporizador;

2. Características

  1. El estado del objeto no se ve afectado por el mundo exterior. El objeto Promise representa una operación asíncrona con tres estados

    • pendiente: en progreso
    • cumplido: ha tenido éxito
    • rechazado: fallido

    Solo el resultado de una operación asíncrona puede determinar en qué estado se encuentra actualmente y ninguna otra operación puede cambiar este estado.

  2. Una vez que cambia el estado, no volverá a cambiar, y este resultado se puede obtener en cualquier momento. Los cambios de estado tienen solo dos estados desde pendingcambiar a fulfilledy desde pendingcambiar a rejected.

3. Uso básico

ES6 estipula que Promiseun objeto es un constructor utilizado para generar Promiseinstancias.

// Promise构造函数接受一个函数(执行器函数)作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
const promise = new Promise(function(resolve, reject) {
    
    
  // ... some code

  if (/* 异步操作成功 */){
    
    
  // 在异步操作成功时调用,并将异步操作的结果,作为参数value传递出去;
    resolve(value);
  } else {
    
    
  // 在异步操作失败时调用,并将异步操作报出的错误,作为参数error/reason传递出去。
    reject(error);
  }
});

Después de generar la instancia de Promise, puede usar el método then para especificar las funciones de devolución de llamada del estado resuelto y el estado rechazado respectivamente.

promise.then(function(value) {
    
    
  // success
}, function(error) {
    
    
  // failure
});

thenEl método puede aceptar dos funciones de devolución de llamada como parámetros.

  • La primera función de devolución de llamada se llama cuando Promisecambia el estado del objeto.resolved
  • La segunda función de devolución de llamada se llama cuando Promisecambia el estado del objeto rejected.

Ambas funciones son opcionales y no es necesario proporcionarlas. Todos aceptan Promiseel valor pasado del objeto como parámetro.

// 创建一个新的p对象promise
const p = new Promise((resolve, reject) => {
    
     // 执行器函数
  // 执行异步操作任务
  setTimeout(() => {
    
    
    const time = Date.now() 
    // 如果当前时间是偶数代表成功,否则失败
    if (time % 2 == 0) {
    
    
      // 如果成功,调用resolve(value)
      resolve('成功的数据,time=' + time)
    } else {
    
    
      // 如果失败,调用reject(reason)
      reject('失败的数据,time=' + time)
    }
  }, 1000);
})

p.then(
  value => {
    
     // 接收得到成功的value数据 onResolved
    console.log('成功的回调', value)  // 成功的回调 成功的数据,time=1615015043258
  },
  reason => {
    
     // 接收得到失败的reason数据 onRejected
    console.log('失败的回调', reason)    // 失败的回调 失败的数据,time=1615014995315
  }
)

4. Por qué usar Promesa

1. La forma de especificar la función de devolución de llamada es más flexible

Antiguo: debe especificarse antes de iniciar la tarea asíncrona

// 1. 纯回调的形式
// 成功的回调函数
function successCallback(result) {
    
    
  console.log("声音文件创建成功:" + result);
}
// 失败的回调函数
function failureCallback(error) {
    
    
  console.log("声音文件创建失败:" + error);
}
// 必须先指定回调函数,再执行异步任务
createAudioFileAsync(audioSettings, successCallback, failureCallback) // 回调函数在执行异步任务(函数)前就要指定

Promesa: iniciar una tarea asíncrona => devolver un objeto de promesa => vincular una función de devolución de llamada al objeto de promesa (incluso se puede especificar después de que finalice la tarea asíncrona)

// 2. 使用Promise
const promise = createAudioFileAsync(audioSettings);  // 执行2秒
setTimeout(() => {
    
    
  promise.then(successCallback, failureCallback) // 也可以获取
}, 3000);

2. Admite llamadas en cadena, que pueden resolver el problema de la devolución de llamadas.

Infierno de devolución de llamada: las funciones de devolución de llamada están anidadas, y el resultado de la ejecución asíncrona de la función de devolución de llamada externa es la condición para la ejecución de la función de devolución de llamada anidada interna.

doSomething(function(result) {
    
    
  doSomethingElse(result, function(newResult) {
    
    
    doThirdThing(newResult, function(finalResult) {
    
    
      console.log('Got the final result:' + finalResult)
    }, failureCallback)
  }, failureCallback)
}, failureCallback)

promiseResolviendo el infierno de devolución de llamada con llamadas encadenadas

doSomething()
  .then(result => doSomethingElse(result))
  .then(newResult => doThirdThing(newResult))
  .then(finalResult => {
    
    console.log('Got the final result:' + finalResult)})
  .catch(failureCallback)

Implementando Ajax con Promises

const getJSON = function(url) {
    
    
  const promise = new Promise(function(resolve, reject){
    
    
    const handler = function() {
    
    
      if (this.readyState !== 4) {
    
    
        return;
      }
      if (this.status === 200) {
    
    
        resolve(this.response);
      } else {
    
    
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
    
    
  console.log('Contents: ' + json);
}, function(error) {
    
    
  console.error('出错了', error);
});

En el código anterior, getJSON es una encapsulación del objeto XMLHttpRequest, que se utiliza para emitir una solicitud HTTP de datos JSON y devolver un objeto Promise. Cabe señalar que dentro de getJSON, tanto la función de resolución como la función de rechazo se llaman con parámetros.

En segundo lugar, el uso de Promise

1. Constructor de promesa: promesa (ejecutor) {}

  • función ejecutora:ejecución síncrona(resolver, rechazar) => {}
  • función de resolución: la función resolver (valor) llamada cuando la definición interna tiene éxito
  • función de rechazo: la función de rechazo (razón) invocada cuando falla la definición interna

Descripción: el ejecutor es el ejecutor, que devolverá la llamada sincrónicamente dentro de Promise, y la operación asincrónica resolver/rechazar se ejecutará en el ejecutor

2. Promise.prototype.then método:(onResolved, onRejected) => {}

指定两个回调(成功+失败)

(1) onResolvedFunción: función de devolución de llamada exitosa(value) => {}

(2) onRejectedFunción: función de devolución de llamada por falla(reason) => {}

Descripción: especifique valuela devolución de llamada exitosa para el éxito y reason la devolución de llamada fallida para el fracaso, y devuelva un nuevo promiseobjeto

2, Promise.prototype.catch método:p.(onRejected) => {}

Especificar una devolución de llamada por falla

(1) Función onRejected: función de devolución de llamada fallida (motivo) => {}

Explicación: Esto es then()azúcar sintáctico, equivalente a:then(undefined, onRejected)

new Promise((resolve, reject) => {
    
     // excutor执行器函数
	 setTimeout(() => {
    
    
	   if(...) {
    
    
	     resolve('成功的数据') // resolve()函数
	   } else {
    
     
	     reject('失败的数据') //reject()函数
	    }
	 }, 1000)
}).then(
	 value => {
    
     // onResolved()函数
	 console.log(value) // 成功的数据
}).catch(
	 reason => {
    
     // onRejected()函数
	  console.log(reason) // 失败的数据
	}
)

3. Método Promise.resolve:Promise.resolve(value) => {}

promiseDevuelve un objeto de éxito/fracaso

value: datos de éxito u promiseobjeto

1. Si el parámetro entrante es un objeto de tipo no Promise, el resultado devuelto es un objeto de promesa exitoso

let p1 = Promise.resolve(521);
console.log(p1); // Promise {<fulfilled>: 521}

inserte la descripción de la imagen aquí
2. Si el parámetro entrante es Promiseun objeto, el resultado del parámetro determina resolveel resultado de

let p2 = Promise.resolve(new Promise((resolve, reject) => {
    
    
    // resolve('OK'); // 成功的Promise
    reject('Error');
}));
console.log(p2);
p2.catch(reason => {
    
    
    console.log(reason);
})

inserte la descripción de la imagen aquí

4. Método Promise.reject:Promise.resolve(reason) => {}

(1) reason: Motivo de la falla

Descripción: Devuelve un promiseobjeto fallido

let p = Promise.reject(521);
let p2 = Promise.reject('iloveyou');
let p3 = Promise.reject(new Promise((resolve, reject) => {
    
    
    resolve('OK');
}));

console.log(p);
console.log(p2);
console.log(p3);

inserte la descripción de la imagen aquí
Promise.resolve()El método / Promise.reject()es un azúcar sintáctico para obtener rápidamente el objeto Promise

5. Método Promise.all:Promise.all(iterable) => {}

  • iterablepromise: un objeto iterable que contiene n , como ArrayoString
  • Devuelve uno nuevo que tiene éxito promisesolo si todos tienen éxito y falla directamente si uno falla.promise
let p1 = new Promise((resolve, reject) => {
    
    
  resolve('OK');
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');

const result = Promise.all([p1, p2, p3]);
console.log(result);

inserte la descripción de la imagen aquí

let p1 = new Promise((resolve, reject) => {
    
    
  resolve('OK');
})
let p2 = Promise.reject('Error');
let p3 = Promise.resolve('Oh Yeah');

const result = Promise.all([p1, p2, p3]);
console.log(result);

inserte la descripción de la imagen aquí

const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)

const pAll = Promise.all([p1, p2, p3])
const pAll2 = Promise.all([p1, p2])
//因为其中p3是失败所以pAll失败
pAll.then(
value => {
    
    
   console.log('all onResolved()', value)
 },
reason => {
    
    
   console.log('all onRejected()', reason) 
 }
)
// all onRejected() 3
pAll2.then(
values => {
    
    
   console.log('all onResolved()', values)
 },
reason => {
    
    
   console.log('all onRejected()', reason) 
 }
)
// all onResolved() [1, 2]

7. Método Promise.race: Promise.race(iterable) => {}

  • iterablepromise: un objeto iterable que contiene n , como ArrayoString
  • Devuelve un nuevo estado de resultado promisecompleto promiseque es el estado de resultado final.
const pRace = Promise.race([p1, p2, p3])
// 谁先完成就输出谁(不管是成功还是失败)
const p1 = new Promise((resolve, reject) => {
    
    
 setTimeout(() => {
    
    
   resolve(1)
 }, 1000)
})
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)

pRace.then(
value => {
    
    
   console.log('race onResolved()', value)
 },
reason => {
    
    
   console.log('race onRejected()', reason) 
 }
)
//race onResolved() 2
let p1 = new Promise((resolve, reject) => {
    
    
  setTimeout(() => {
    
    
      resolve('OK');
  }, 1000);
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');

//调用
const result = Promise.race([p1, p2, p3]);

console.log(result);

inserte la descripción de la imagen aquí

3. Varias cuestiones clave de la promesa

1. ¿Cómo cambiar el estado de promesa?

(1) resolve(value): Si la corriente se pendingconvertiráresolved

(2) reject(reason): Si está actualmente, pendingse convertirá en `rechazado``

(3) Lanzar una excepción: si es actualmente, pendingse convertirá enrejected

const p = new Promise((resolve, reject) => {
    
    
  //resolve(1) // promise变为resolved成功状态
  //reject(2) // promise变为rejected失败状态
  throw new Error('出错了') // 抛出异常,promise变为rejected失败状态,reason为抛出的error
})
p.then(
  value => {
    
    },
  reason => {
    
    console.log('reason',reason)}
)
// reason Error:出错了

2. Una promesa especifica múltiples funciones de devolución de llamada de éxito/fallo, ¿serán llamadas todas?

Llamado cuando la promesa cambia al estado correspondiente

const p = new Promise((resolve, reject) => {
    
    
  //resolve(1)
  reject(2)
})
p.then(
  value => {
    
    },
  reason => {
    
    console.log('reason',reason)}
)
p.then(
  value => {
    
    },
  reason => {
    
    console.log('reason2',reason)}
)
// reason 2
// reason2 2

3. ¿Cuál debería cambiar el estado de promesa y especificar primero la función de devolución de llamada?

(1) Ambos son posibles. En circunstancias normales, la devolución de llamada se especifica primero y luego se cambia el estado, pero también es posible cambiar el estado primero y luego especificar la devolución de llamada.

(2) ¿Cómo cambiar el estado primero y luego especificar la devolución de llamada?

① Llame a resolve()/reject() directamente en el ejecutor

② Demora más antes de llamar entonces()

let p = new Promise((resolve, reject) => {
    
    
  // setTimeout(() => {
    
    
      resolve('OK');
  // }, 1000); // 有异步就先指定回调,否则先改变状态
});

p.then(value => {
    
    
  console.log(value);
},reason=>{
    
    
  
})

(3) ¿Cuándo estarán disponibles los datos?

① Si la devolución de llamada se especifica primero, cuando cambie el estado, se llamará a la función de devolución de llamada para obtener los datos.

② Si el estado se cambia primero, cuando se especifica la devolución de llamada, se llamará a la función de devolución de llamada para obtener los datos

new Promise((resolve, reject) => {
    
    
  setTimeout(() => {
    
    
    resolve(1) // 改变状态
  }, 1000)
}).then( // 指定回调函数 (先指定)
  value => {
    
    },
  reason =>{
    
    }
)

En este punto, primero especifique la función de devolución de llamada, guarde la función de devolución de llamada especificada actualmente, luego cambie el estado (mientras especifica los datos) y luego ejecute la función de devolución de llamada previamente guardada de forma asíncrona.

new Promise((resolve, reject) => {
    
    
  resolve(1) // 改变状态
}).then( // 指定回调函数
  value => {
    
    },
  reason =>{
    
    }
)

De esta forma de escritura, primero cambie el estado (al mismo tiempo especifique los datos), luego especifique la función de devolución de llamada (no es necesario volver a guardar) y ejecute directamente la función de devolución de llamada de forma asíncrona

4. ¿Qué determina el estado de resultado de la nueva promesa devuelta por promise.then()?

(1) Expresión simple: determinada por el resultado de la ejecución de la función de devolución de llamada especificada por then()

let p = new Promise((resolve, reject) => {
    
    
  resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
    
    
  console.log(value);
}, reason => {
    
    
  console.warn(reason);
});

console.log(result);

inserte la descripción de la imagen aquí

(2) Expresión detallada:

① Si se lanza una excepción, la nueva promesa se rechaza, el motivo es la excepción lanzada

let p = new Promise((resolve, reject) => {
    
    
  resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
    
    
  //1. 抛出错误
  throw '出了问题';
}, reason => {
    
    
  console.warn(reason);
});

console.log(result);

inserte la descripción de la imagen aquí
② Si se devuelve un valor que no es una promesa, la nueva promesa se resuelve y el valor es el valor devuelto

let p = new Promise((resolve, reject) => {
    
    
  resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
    
    
	//2. 返回结果是非 Promise 类型的对象
	return 521;
}, reason => {
    
    
  console.warn(reason);
});

console.log(result);

inserte la descripción de la imagen aquí

③ Si se devuelve otra nueva promesa, el resultado de esta promesa se convertirá en el resultado de la nueva promesa

let p = new Promise((resolve, reject) => {
    
    
  resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
    
    
	//3. 返回结果是 Promise 对象
	return new Promise((resolve, reject) => {
    
    
		// resolve('success');
		reject('error');
	});
}, reason => {
    
    
  console.warn(reason);
});

console.log(result);

inserte la descripción de la imagen aquí

new Promise((resolve, reject) => {
    
    
  resolve(1)
}).then(
  value => {
    
    
    console.log('onResolved1()', value)
  },
  reason => {
    
    
    console.log('onRejected1()', reason)
  }
).then(
  value => {
    
    
    console.log('onResolved2()', value)
  },
  reason => {
    
    
    console.log('onRejected2()', reason)
  }
)
// onResolved1() 1
// onResolved2() undefined
new Promise((resolve, reject) => {
    
    
  resolve(1)
}).then(
  value => {
    
    
    console.log('onResolved1()', value)
    //return 2                   // onResolved2() 2
    //return Promise.resolve(3)  // onResolved2() 3
    //return Promise.reject(4)   // onRejected2() 4
    //throw 5                    // onRejected2() 5
  },
  reason => {
    
    
    console.log('onRejected1()', reason)
  }
).then(
  value => {
    
    
    console.log('onResolved2()', value)
  },
  reason => {
    
    
    console.log('onRejected2()', reason)
  }
)
// onResolved1() 1
// onResolved2() undefined
// Promise {<fulfilled>: undefined}
// 对应输出如上所示

5. ¿Cómo encadena la promesa múltiples tareas de operación?

(1) promisedevuelve then()una nueva llamada en cadena promiseque se puede abrirthen()

(2) thenMúltiples tareas sincrónicas/asincrónicas están conectadas en serie a través de la llamada en cadena de

let p = new Promise((resolve, reject) => {
    
    
  setTimeout(() => {
    
    
      resolve('OK');
  }, 1000);
});

p.then(value => {
    
    
  return new Promise((resolve, reject) => {
    
    
      resolve("success");
  });
}).then(value => {
    
    
  console.log(value); // success
}).then(value => {
    
    
  console.log(value); // undefined
})
new Promise((resolve, reject) => {
    
    
  setTimeout(() => {
    
    
    console.log('执行任务1(异步)')
    resolve(1)
  }, 1000)
}).then(
  value => {
    
    
    console.log('任务1的结果', value)
    console.log('执行任务2(同步)')
    return 2 // 同步任务直接return返回结果
  }
).then(
  value => {
    
    
    console.log('任务2的结果', value)
    return new Promise((resolve, reject) => {
    
     // 异步任务需要包裹在Promise对象中
      setTimeout(() => {
    
    
        console.log('执行任务3(异步)')
        resolve(3)
      }, 1000)
    })
  }
).then(
  value => {
    
    
    console.log('任务3的结果', value)
  }
)
// 执行任务1(异步)
// 任务1的结果 1
// 执行任务2(同步)
// 任务2的结果 2
// 执行任务3(异步)
// 任务3的结果 3

6. ¿Romper la cadena de promesas?

(1) Al usar promisela thenllamada en cadena de , se interrumpirá en el medio y no se llamará a la función de devolución de llamada posterior

(2) Métodos:Devolver un objeto penddingde estado en la función de devolución de llamadapromise

new Promise((resolve, reject) => {
    
    
   //resolve(1)
   reject(1)
}).then(
  value => {
    
    
    console.log('onResolved1()', value)
    return 2
  }
).then(
  value => {
    
    
    console.log('onResolved2()', value)
    return 3
  }
).then(
  value => {
    
    
    console.log('onResolved3()', value)
  }
).catch(
  reason => {
    
    
    console.log('onRejected1()', reason)
  }
).then(
  value => {
    
    
    console.log('onResolved4()', value)
  },
  reason => {
    
    
    console.log('onRejected2()', reason)
  }
)
// onRejected1() 1
// onResolved4() undefined

Supongo que te gusta

Origin blog.csdn.net/Bon_nenul/article/details/128224182
Recomendado
Clasificación