Método estático de promesa escrita a mano

promesa manuscrita

Fondo frontal: promesa manuscrita en lengua vernácula

resolver, rechazar

Como método llamado directamente por la clase, es naturalmente un método estático.
**El principio de resolver y rechazar es instanciar una promesa internamente y luego llamar a resolver o rechazar. **La esencia no es diferente de instanciar la promesa llámese usted mismo.

class LcPromise {
    
    
  constructor(executed) {
    
    }
  then(onFulfilled, onRejected) {
    
    }
	catch(onRejected) {
    
    }
  finally(fn) {
    
    }

  static resolve(value) {
    
    
    return new LcPromise((resolve, reject) => resolve(value))
  }

  static reject(reason) {
    
    
    return new LcPromise((resolve, reject) => reject(reason))
  }
}

todo, todo arreglado

Uso de todos los métodos: reciba una matriz de instancias de promesa, espere a que se cumplan todas las promesas en la matriz, luego llame a onFulfilled, siempre que haya una promesa rechazada, luego llame a onRejected inmediatamente.

Promise.all([]).then(onFulfilled).catch(onRejected)

A partir de esto, podemos ver que todos deben devolver una instancia de promesa, de lo contrario, cómo llamar entonces. Podemos esperar los resultados de las instancias de promesa en la matriz una por una. Cuando todas las instancias de promesa se ejecutan en Cumplido, significa que todo ya está en el estado cumplido, y las instancias de promesa devueltas por resolver todo. Si uno de ellos ejecuta onRejected, significa que hay un error en todos, y se puede rechazar toda la instancia de promesa de todos.
La clave de todo el problema es cuando la promesa devuelta por todas las ejecuciones se resuelve y cuando las ejecuciones rechazan.

static all(promiseArr) {
    
    
  const allResult = [];
  return new LcPromise((resolve, reject) => {
    
    
    promiseArr.forEach((promise) => {
    
    
      // 执行每个 promise 实例
      promise.then(
        (res) => {
    
    
          // 收集每个 promise 的成功结果
          allResult.push(res);
          // 当收集完所有的 promise,说明整体的 promise 应该为 fulfilled 状态了,执行 resolve
          if (allResult.length === promiseArr.length) resolve(allResult);
        },
        (err) => {
    
    
          // 只要有一个 promise rejected 了,就执行整个 promise 的 reject 函数
          reject(err);
        }
      );
    });
  });
}

allSettled es similar a all, la diferencia es que cuando hay una promesa rechazada en la matriz de promesas recibida por allSettled, no interrumpirá la ejecución de toda la función allSettled, y la promesa devuelta por allSettled no se rechazará, seguirá siendo estar pendiente y continuar ejecutando los subsiguientes en la promesa de matriz. Significa que la promesa devuelta por allSettled no ejecutará la función de rechazo, y debe estar en estado cumplido al final. Para las promesas en estado rechazado en la matriz, el valor de retorno de allSettled es un objeto de matriz. El objeto contiene el estado y resultado o mensaje de error de cada promesa.

static allSettled(promiseArr) {
    
    
  const allResult = [];
  return new LcPromise((resolve, reject) => {
    
    
    promiseArr.forEach((promise) => {
    
    
      promise.then(
        (res) => {
    
    
          allResult.push({
    
     status: "fulfilled", res: res });
          if (allResult.length === promiseArr.length) resolve(allResult);
        },
        (err) => {
    
    
          allResult.push({
    
     status: "rejected", err: err });
          if (allResult.length === promiseArr.length) resolve(allResult);
        }
      );
    });
  });
}

prueba:

const p1 = new LcPromise((resolve, reject) => {
    
    
  resolve(1111);
});
const p2 = new LcPromise((resolve, reject) => {
    
    
  // resolve(2222);
  reject("hhh");
});
const p3 = new LcPromise((resolve, reject) => {
    
    
  resolve(3333);
});

LcPromise.all([p1, p2, p3])
  .then((res) => console.log(res))
  .catch((err) => console.log(err));

// hhh

LcPromise.allSettled([p1, p2, p3])
  .then((res) => console.log(res))
  .catch((err) => console.log(err));

// [
//   { status: 'fulfilled', res: 1111 },
//   { status: 'rejected', err: 'hhh' },
//   { status: 'fulfilled', res: 3333 }
// ]

raza, cualquier

Uso del método de carrera: básicamente similar a todos, la diferencia es que siempre que haya una promesa en la matriz que confirme el estado, el estado de la promesa devuelta por toda la carrera se determina de inmediato.
Entonces, si una promesa ejecuta el método entonces, el método de resolución o el método de rechazo de la promesa general se pueden ejecutar de inmediato.

static race(promiseArr) {
    
    
  return new LcPromise((resolve, reject) => {
    
    
    promiseArr.forEach((promise) => {
    
    
      // 有一个 promise 确定了状态,就立即确定了整体 promise 的状态
      promise.then(res => {
    
    
        resolve(res)
      }, err => {
    
    
        reject(err)
      })
    })
  })
}

El uso de any es ejecutar resolve siempre que se cumpla una promesa en la matriz y se cumpla la promesa general. La función de rechazo se ejecuta solo cuando se rechazan todas las promesas en la matriz, se rechaza el total y se devuelve una matriz de errores combinada que contiene todos los mensajes de error new AggregateError(arr).
Tenga en cuenta que este constructor no está implementado en nodejs y solo se puede probar en el navegador. Tiene un atributo de errores, puede ver los mensajes de error.

static any(promiseArr) {
    
    
  return new LcPromise((resolve, reject) => {
    
    
    const reasonArr = []
    promiseArr.forEach((promise) => {
    
    
      promise.then(res => {
    
    
        resolve(res)
      }, err => {
    
    
        reasonArr.push(err)
        if (promiseArr.length === reasonArr.length) reject(new AggregateError(reasonArr))
      })
    })
  })
}

prueba:

const p1 = new LcPromise((resolve, reject) => {
    
    
  setTimeout(() => {
    
    
    resolve(1111);
  }, 3000);
});
const p2 = new LcPromise((resolve, reject) => {
    
    
  // resolve(2222);
  setTimeout(() => {
    
    
    reject("hhh");
  }, 1000);
});
const p3 = new LcPromise((resolve, reject) => {
    
    
  setTimeout(() => {
    
    
    resolve(3333);
  }, 2000);
});

LcPromise.race([p1, p2, p3])
  .then((res) => console.log(res))
  .catch((err) => console.log(err));

// hhh 打印最快确定状态的信息
// 所有 promise rejected 的情况
const p1 = new LcPromise((resolve, reject) => {
    
    
  setTimeout(() => {
    
    
    // resolve(1111);
    reject("h1");
  }, 3000);
});
const p2 = new LcPromise((resolve, reject) => {
    
    
  // resolve(2222);
  setTimeout(() => {
    
    
    reject("h2");
  }, 1000);
});
const p3 = new LcPromise((resolve, reject) => {
    
    
  setTimeout(() => {
    
    
    // resolve(3333);
    reject("h3");
  }, 2000);
});

LcPromise.any([p1, p2, p3])
  .then((res) => console.log(res))
  .catch((err) => console.log(err.errors));

// (3) ['h2', 'h3', 'h1']

promesa completa

const PROMISE_STATUS_PENDING = "pending";
const PROMISE_STATUS_FULFILLED = "fulfilled";
const PROMISE_STATUS_REJECTED = "rejected";

const execFunctionWithCatchError = (execFn, value, resolve, reject) => {
    
    
  try {
    
    
    const res = execFn(value);
    resolve(res);
  } catch (error) {
    
    
    reject(error);
  }
};

class LcPromise {
    
    
  constructor(executed) {
    
    
    this.status = PROMISE_STATUS_PENDING;

    this.value = undefined;
    this.reason = undefined;

    this.onFulfilledFns = [];
    this.onRejectedFns = [];

    const resolve = (value) => {
    
    
      this.value = value;
      queueMicrotask(() => {
    
    
        if (this.status != PROMISE_STATUS_PENDING) return;
        this.status = PROMISE_STATUS_FULFILLED;
        this.onFulfilledFns.forEach((fns) => fns(this.value));
      });
    };
    const reject = (reason) => {
    
    
      this.reason = reason;
      queueMicrotask(() => {
    
    
        if (this.status != PROMISE_STATUS_PENDING) return;
        this.status = PROMISE_STATUS_REJECTED;
        this.onRejectedFns.forEach((fns) => fns(this.reason));
      });
    };

    executed(resolve, reject);
  }

  then(onFulfilled, onRejected) {
    
    
    onFulfilled = onFulfilled || ((value) => value);
    onRejected =
      onRejected ||
      ((err) => {
    
    
        throw err;
      });

    return new LcPromise((resolve, reject) => {
    
    
      // 在 resolve reject 中执行
      if (onFulfilled)
        this.onFulfilledFns.push(() => {
    
    
          execFunctionWithCatchError(onFulfilled, this.value, resolve, reject);
        });
      if (onRejected)
        this.onRejectedFns.push(() => {
    
    
          execFunctionWithCatchError(onRejected, this.reason, resolve, reject);
        });

      // 在自身中执行
      if (this.status === PROMISE_STATUS_FULFILLED) {
    
    
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject);
      }
      if (this.status === PROMISE_STATUS_REJECTED) {
    
    
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject);
      }
    });
  }

  catch(onRejected) {
    
    
    return this.then(undefined, onRejected);
  }

  finally(fn) {
    
    
    this.then(fn, fn);
  }

  static resolve(value) {
    
    
    return new LcPromise((resolve, reject) => resolve(value));
  }

  static reject(reason) {
    
    
    return new LcPromise((resolve, reject) => reject(reason));
  }

  static all(promiseArr) {
    
    
    const allResult = [];
    return new LcPromise((resolve, reject) => {
    
    
      promiseArr.forEach((promise) => {
    
    
        // 执行每个 promise 实例
        promise.then(
          (res) => {
    
    
            // 收集每个 promise 的成功结果
            allResult.push(res);
            // 当收集完所有的 promise,说明整体的 promise 应该为 fulfilled 状态了,执行 resolve
            if (allResult.length === promiseArr.length) resolve(allResult);
          },
          (err) => {
    
    
            // 只要有一个 promise rejected 了,就执行整个 promise 的 reject 函数
            reject(err);
          }
        );
      });
    });
  }

  static allSettled(promiseArr) {
    
    
    const allResult = [];
    return new LcPromise((resolve, reject) => {
    
    
      promiseArr.forEach((promise) => {
    
    
        promise.then(
          (res) => {
    
    
            allResult.push({
    
     status: "fulfilled", res: res });
            if (allResult.length === promiseArr.length) resolve(allResult);
          },
          (err) => {
    
    
            allResult.push({
    
     status: "rejected", err: err });
            if (allResult.length === promiseArr.length) resolve(allResult);
          }
        );
      });
    });
  }

  static race(promiseArr) {
    
    
    return new LcPromise((resolve, reject) => {
    
    
      promiseArr.forEach((promise) => {
    
    
        promise.then(
          (res) => {
    
    
            resolve(res);
          },
          (err) => {
    
    
            reject(err);
          }
        );
      });
    });
  }

  static any(promiseArr) {
    
    
    return new LcPromise((resolve, reject) => {
    
    
      const reasonArr = [];
      promiseArr.forEach((promise) => {
    
    
        promise.then(
          (res) => {
    
    
            resolve(res);
          },
          (err) => {
    
    
            reasonArr.push(err);
            if (promiseArr.length === reasonArr.length)
              reject(new AggregateError(reasonArr));
          }
        );
      });
    });
  }
}

Supongo que te gusta

Origin blog.csdn.net/qq_43220213/article/details/129775183
Recomendado
Clasificación