Прототип обещания (присоединиться к конечному автомату)
function Promise(executor){
let self = this;
self.status = 'pending';
self.value = undefined;
self.reason = undefined;
function resolve(value){
if( self.status === 'pending'){
self.status = 'fulfilled';
self.value = value;
}
}
function reject(reason){
if( self.status === 'pending'){
self.status = 'rejected';
self.reason = reason;
}
}
executor(resolve,reject);
}
Promise.prototype.then = function(onFulfilled,onRejected){
let self = this;
if(self.status === 'fulfilled'){
onFulfilled(self.value);
}
if(self.status === 'rejected'){
onRejected(self.reason);
}
}
module.exports = Promise;
Тестовый пример 1
let Promise = require('Mypromise');
let promise = newPromise(function(resolve,reject){
resolve(results)
})
promise.then(function(data){
console.log(data);
},function(err){
console.log(err);
})
Сначала мы определяем переменную состояния состояния, промис по умолчанию находится в состоянии ожидания
Промис получает функцию-исполнитель, которая выполняется при создании экземпляра промиса, поэтому запустите исполнителя в конструкторе промиса.Исполнитель должен получить разрешение в качестве функции обратного вызова, когда выполнение успешно, и отклонение в качестве функции обратного вызова, когда выполнение завершается неудачно. , поэтому определены методы разрешения и отклонения
Resolve получает возвращаемый результат успешного выполнения в качестве параметра.
reject получает возвращаемый результат сбоя выполнения в качестве параметра
Поэтому здесь определено значение, указывающее на успешный результат, а причина указывает на причину ошибки.
После вызова разрешения или отклонения обещание войдет в состояние выполненного успеха или отклоненного состояния отказа, и только когда обещание находится в состоянии ожидания, оно может переключиться в состояние успеха/ошибки.
Экземпляр промиса должен использовать метод then, чтобы зарегистрировать метод обратного вызова успешного/неудачного выполнения, а затем, в зависимости от состояния промиса, обратный вызов, чтобы определить, был ли вызов успешным или нет.
Реализация такого простого промиса написана
Добавьте асинхронную обработку обратного вызова, поддержите регистрацию нескольких, а затем
function Promise(executor){
let self = this;
self.status = 'pending';
self.value = undefined;
self.reason = undefined;
self.onResolvedCallbacks = [];
self.onRejectedCallbacks = [];
function resolve(value){
if( self.status === 'pending'){
self.status = 'fulfilled';
self.value = value;
self.onResolvedCallbacks.forEach(function(fn){
fn();
})
}
}
function reject(reason){
if( self.status === 'pending'){//只能从pending状态切换到rejected状态
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach(function(fn){
fn();
})
}
}
executor(resolve,reject);
}
Promise.prototype.then = function(onFulfilled,onRejected){
let self = this;
if(self.status === 'fulfilled'){
onFulfilled(self.value);
}
if(self.status === 'rejected'){
onRejected(self.reason);
}
if(self.status === 'pending'){
self.onResolvedCallbacks.push( function(){
onFulfilled(self.value)
});
self.onRejectedCallbacks.push( function(){
onRejected(self.reason)
});
}
}
module.exports = Promise;
Тестовый пример 2
let promise = new Promise(function(resolve,reject){
http.get(url, function(results) {
resolve(results)
})
})
promise.then(function(data){
console.log('data',data);
},function(err){
console.log('err',err);
})
promise.then(function(data){
console.log('data',data);
},function(err){
console.log('err',err);
})
promise.then(function(data){
console.log('data',data);
},function(err){
console.log('err',err);
})
Промис в основном используется для обработки асинхронных обратных вызовов. В приведенном выше примере инициируется HTTP-запрос. После успешного выполнения запроса для инициирования успешного обратного вызова используется метод разрешения, а затем вызывается несколько методов обратного вызова для регистрации нескольких успешных и неудачных попыток. выполнение выполнено успешно, собственное обещание будет выполнять каждый последующий обратный вызов успеха
Из-за асинхронного запроса, когда вызывается then, обещание все еще находится в состоянии ожидания, поэтому нам нужно временно сохранить зарегистрированный к тому времени метод обратного вызова, чтобы его можно было вызвать обратно, когда он завершится успешно или неудачно. onResolvedCallbacks и onRejectedCallbacks определены для хранения успешных и неудачных обратных вызовов, зарегистрированных соответствующим методом, как показано в примере выше.
Затем может вызывать регистрацию несколько раз, поэтому onResolvedCallbacks = [], это массив
Когда выполнение будет успешным, будет вызвано разрешение, затем, когда мы реализуем метод разрешения, мы снова вызовем все успешные обратные вызовы, что и является этим кодом.
self.onResolvedCallbacks.forEach(function(fn){
fn();
})
обработка исключений исполнителя
Когда выполняется асинхронная операция, может возникнуть исключение, и try/catch должен поймать исключение и перевести промис в состояние отклонено.
try {
executor(resolve,reject); //捕获的时候发生异常,执行reject
} catch (error) {
reject(error)
}
Выбросить новый тест Error ('ошибка') может быть запущен в исполнителе
Обработка исключений для связанных обратных вызовов
Затем, будь то успешный обратный вызов или неудачный обратный вызов, пока есть результат возврата, он перейдет к следующему затем (разные обратные вызовы, которые входят в следующий затем в соответствии с разными результатами возврата, правила другие часть моей статьи.nuggets.capable/post/684490…
Промисы реализуют цепочку вызовов, возвращая новые промисы в then.Представьте: новый промис может продолжать вызывать метод then. Метод then дополняется следующим образом
Promise.prototype.then = function(onFulfilled,onRejected){
let self = this;
let promise2; //then返回的新Promise
if(self.status === 'fulfilled'){
//onFilfilled会同步执行,并返回新的promise2
promise2 = new Promise(function (resolve,reject) {
onFulfilled(self.value);
});
}
if(self.status === 'rejected'){
promise2 = new Promise(function (resolve,reject) {
onRejected(self.reason);
});
}
if(self.status === 'pending'){
promise2 = new Promise(function (resolve,reject) {
self.onResolvedCallbacks.push( function(){
//捕获异步回调时的异常,如果有进入promise2的失败态
try{
onFulfilled(self.value);
}catch (e){
reject(e);
}
});
self.onRejectedCallbacks.push( function(){
try{
onRejected(self.reason);
}catch (e){
reject(e);
}
});
});
}
return promise2;
}
Первый оператор if в приведенном выше коде возвращает новое обещание 2 при успешном выполнении обратного вызова.Поскольку исполнитель будет выполняться немедленно при выполнении нового обещания, метод onFulfilled (успешный обратный вызов) будет выполняться синхронно, и исключение будет перехвачено; второй оператор if То же верно и для обратных вызовов с ошибкой.
Третий оператор if, если это асинхронный обратный вызов, при выполнении метода-исполнителя promise2 просто добавьте успешный обратный вызов onFulfilled в очередь успешных обратных вызовов onResolvedCallbacks (то же самое верно и для отказа).Когда успешный обратный вызов действительно выполняется, если возникает исключение, его нужно поймать. , и войти в состояние отказа нового promise2
Обработка возвращаемого значения связанного обратного вызова
Если первое обещание возвращает нормальное значение, оно перейдет к следующему успешному обратному вызову
Если первое обещание возвращает обещание, вам нужно дождаться выполнения результата возвращенного обещания, прежде чем передать его следующему.
Итак, мы используем x для получения возвращаемого значения первого, затем пусть x = onFulfilled(self.value);
x может быть обычным значением, обещанием или обещанием, реализованным другими.Здесь реализован метод resolvePromise для единообразной обработки возвращаемого значения.
Код then обновляется следующим образом: оба используют x для получения возвращаемого значения функции обратного вызова и вызывают resolvePromise для обработки
Promise.prototype.then = function(onFulfilled,onRejected){
let self = this;
let promise2;//then返回的新Promise
if(self.status === 'fulfilled'){
promise2 = new Promise(function (resolve,reject) {
let x= onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject);
});
}
if(self.status === 'rejected'){
promise2 = new Promise(function (resolve,reject) {
let x= onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject);
});
}
if(self.status === 'pending'){
promise2 = new Promise(function (resolve,reject) {
self.onResolvedCallbacks.push( function(){
try{
let x= onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject);
}catch (e){
reject(e);
}
});
self.onRejectedCallbacks.push( function(){
try{
let x= onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject);
}catch (e){
reject(e);
}
});
});
}
return promise2;
}
Реализация resolvePromise выглядит следующим образом.
параметр:
p2 : обещание экземпляра второго, затем
x: возвращаемое значение первого, затем
разрешить/отклонить : разрешить/отклонить p2
function resolvePromise(p2,x,resolve,reject){
if(p2 === x){ //报一个类型错误
return reject(new TypeError('循环引用了'));
}
//判断x是不是promise
if(x!== null || (typeof x === 'object'||typeof x === 'function')){
//x可能是promise 看对象中是否有then方法,有then就认为是promise
//取then方法有可能异常,发生异常就进入p2的失败态
try {
let then = x.then;
if(typeof then === 'function'){
//认为x是一个promise,立刻执行该promise的then方法
//如果x进入成功态,会触发成功回调
then.call(x,function(y){
//y可能还是一个promise,继续解析,直到返回的是一个普通值
resolvePromise(p2,y,resolve,reject);
},function(err){ //如果x进入失败态,会触发p2的失败态
reject(err);
});
}else{ //如果then不是方法,直接认为返回一个对象,调用p2成功态
resolve(x);
}
} catch (error) {
reject(error);
}
}else{ //x是普通值,调用p2成功态
resolve(x);
}
};
Вызовите разрешение несколько раз, отклоните и добавьте вызываемый флаг
Если кто-то напишет код как
let p1= new Promise(function (resolve,reject) {
resolve('success');
reject('fail1');
});
Способ обработки обещания заключается в том, что как только оно переходит в успешное состояние, оно считается успешным, и отклонение больше не вызывается, и наоборот.
Здесь, добавив флаг call в метод resolvePromise, это означает, что было введено разрешение или отклонение; если call имеет значение true, возвращайтесь напрямую, если false, установите значение true.
function resolvePromise(p2, x, resolve, reject) {
if (p2 === x) { //这里应该报一个类型错误,有问题
return reject(new TypeError('循环引用了'))
}
let called; // 表示是否调用过成功或者失败
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, function (y) {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject)
}, function (err) { //失败
if (called) return;
called = true;
reject(err);
})
} else {
resolve(x)
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else { // 说明是一个普通值1
resolve(x); // 表示成功了
}
}
Проникновение в обещания
Мы ничего не можем написать тогда
p1.then().then().then(function(data){
console.log('data',data);
},function(err){
console.log('err',err);
})
Результат выполнения p1 по-прежнему будет проникать в соответствующий обратный вызов последнего, а затем
Об этом нужно судить в начале метода then, есть ли метод разрешения/отклонения, если нет, то нужно указать метод обработки по умолчанию
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled :
function(value){ //默认的成功回调,返回一个值,就会进入下一个then的成功回调
return value;
};
onRejected = typeof onRejected === 'function' ? onRejected :
function(err){//默认的失败回调,抛出异常,就会进入下一个then的失败回调
throw err;
};
реализовать улов
Метод отлова ошибок catch эквивалентен последующему вызову метода error
Promise.prototype.catch = function (callback) {
return this.then(null,callback);
}
Реализовать обещание.все
all получает массив, членами которого являются экземпляры обещаний, последовательно выполняет их и последовательно возвращает результаты выполнения.
Когда все промисы успешно выполнены, он переходит в состояние успеха, а если один из них терпит неудачу, он переходит в состояние отказа.
//promises是一个promise的数组
Promise.all = function (promises) {
return new Promise(function (resolve, reject) {
let arr = []; //arr是最终返回值的结果
let count = 0; // 表示成功了多少次
function processData(index, y) {
arr[index] = y;
if (++count === promises.length) {
resolve(arr);
}
}
for (let i = 0; i < promises.length; i++) {
promises[i].then(function (y) {
processData(i, y)
}, reject) //有一个失败,就调用失败回调
}
})
};
Реализовать Promise.race
Параметры такие же, как и у всех, до тех пор, пока один промис выполняется, он успешен. Если один терпит неудачу, он терпит неудачу, а другие промисы продолжают выполняться
Promise.race = function (promises) {
return new Promise(function (resolve, reject) {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve,reject)
}
})
};
Реализовать Promise.resolve/Promise.reject
Promise.resolve можно понимать как создание успешного обещания.
Promise.resolve = function(value){
return new Promise(function(resolve,reject){
resolve(value);
})
}
Promise.reject генерирует невыполненное обещание
Promise.reject = function(reason){
return new Promise(function(resolve,reject){
reject(reason);
})
}
Спецификация Promises/A+ явно требует, чтобы обратные вызовы выполнялись асинхронно, чтобы обеспечить согласованный и надежный порядок выполнения.
Здесь Settimeout используется для имитации асинхронного исполнения, и все успешные и неудачные обратные вызовы обернуты с Settimeout. Поскольку асинхронное исполнение, необходимо ловить исключения
Окончательная реализация Promise выглядит следующим образом (всего)
function Promise(executor) { // executor是一个执行函数
let self = this;
self.status = 'pending';
self.value = undefined; // 默认成功的值
self.reason = undefined; // 默认失败的原因
self.onResolvedCallbacks = []; // 存放then成功的回调
self.onRejectedCallbacks = []; // 存放then失败的回调
function resolve(value) { // 成功状态
if (self.status === 'pending') {
self.status = 'resolved';
self.value = value;
self.onResolvedCallbacks.forEach(function (fn) {
fn();
});
}
}
function reject(reason) { // 失败状态
if (self.status === 'pending') {
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach(function (fn) {
fn();
})
}
}
try {
executor(resolve, reject)
} catch (e) { // 捕获的时候发生异常,就直接失败了
reject(e);
}
}
function resolvePromise(promise2, x, resolve, reject) {
// 有可能这里返回的x是别人的promise
// 尽可能允许其他乱写
if (promise2 === x) { //这里应该报一个类型错误,有问题
return reject(new TypeError('循环引用了'))
}
// 看x是不是一个promise,promise应该是一个对象
let called; // 表示是否调用过成功或者失败
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
// 可能是promise {},看这个对象中是否有then方法,如果有then我就认为他是promise了
try { // {then:1}
let then = x.then;
if (typeof then === 'function') {
// 成功
then.call(x, function (y) {
if (called) return
called = true
// y可能还是一个promise,在去解析直到返回的是一个普通值
resolvePromise(promise2, y, resolve, reject)
}, function (err) { //失败
if (called) return
called = true
reject(err);
})
} else {
resolve(x)
}
} catch (e) {
if (called) return
called = true;
reject(e);
}
} else { // 说明是一个普通值1
resolve(x); // 表示成功了
}
}
Promise.prototype.then = function (onFulfilled, onRjected) {
//成功和失败默认不穿给一个函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {
return value;
}
onRjected = typeof onRjected === 'function' ? onRjected : function (err) {
throw err;
}
let self = this;
let promise2; //返回的promise
if (self.status === 'resolved') {
promise2 = new Promise(function (resolve, reject) {
// 当成功或者失败执行时有异常那么返回的promise应该处于失败状态
// x可能是一个promise 也有可能是一个普通的值
setTimeout(function () {
try {
let x = onFulfilled(self.value);
// x可能是别人promise,写一个方法统一处理
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
})
}
if (self.status === 'rejected') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let x = onRjected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
})
}
// 当调用then时可能没成功 也没失败
if (self.status === 'pending') {
promise2 = new Promise(function (resolve, reject) {
// 此时没有resolve 也没有reject
self.onResolvedCallbacks.push(function () {
setTimeout(function () {
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
})
});
self.onRejectedCallbacks.push(function () {
setTimeout(function () {
try {
let x = onRjected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
});
})
}
return promise2;
}
// 捕获错误的方法
Promise.prototype.catch = function (callback) {
return this.then(null, callback)
}
// 解析全部方法
Promise.all = function (promises) {
//promises是一个promise的数组
return new Promise(function (resolve, reject) {
let arr = []; //arr是最终返回值的结果
let i = 0; // 表示成功了多少次
function processData(index, y) {
arr[index] = y;
if (++i === promises.length) {
resolve(arr);
}
}
for (let i = 0; i < promises.length; i++) {
promises[i].then(function (y) {
processData(i, y)
}, reject)
}
})
};
// 只要有一个promise成功了 就算成功。如果第一个失败了就失败了
Promise.race = function (promises) {
return new Promise(function (resolve, reject) {
for (var i = 0; i < promises.length; i++) {
promises[i].then(resolve,reject)
}
})
}
// 生成一个成功的promise
Promise.resolve = function(value){
return new Promise(function(resolve,reject){
resolve(value);
})
}
// 生成一个失败的promise
Promise.reject = function(reason){
return new Promise(function(resolve,reject){
reject(reason);
})
}
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise(function (resolve, reject) {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd
}
module.exports = Promise;