JavaScript中异步方法原理与实现3.21

当笔记本慢慢记录了
JavaScript为什么要出现promise与async

处理异步的三种方法

红绿灯

公共代码

js 复制代码
题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯两秒亮一次,不断交替循环
   function red() {
        console.log("red");
      }
      function green() {
        console.log("green");
      }
      function yellow() {
        console.log("yellow");
      }
setTimeOut实现红绿灯
js 复制代码
      var light = (time, cb) => {
        setTimeout(cb, time);
      };
      function step() {
        light(3000, () => {
          red();
          light(1000, () => {
            green();
            light(2000, () => {
              yellow();
              step();
            });
          });
        });
      }
      step();
promise实现红绿灯
js 复制代码
var light = (timmer, cb) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      cb();
      resolve();
    }, timmer);
  });
};

var step = () => {
  new Promise((resolve)=>resolve())
    .then(() => {
      return light(3000, red);
    })
    .then(() => {
      return light(1000, green);
    })
    .then(() => {
      return light(2000, yellow);
    })
    .then(() => {
      step();
    })
    .catch(err => console.log(err));
};

step();
async awiat
js 复制代码
const light = (timmer, cb) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      cb();
      resolve();
    }, timmer);
  });
};
async function step() {
  await light(3000, red);
  await light(1000, green);
  await light(2000, yellow);
  step();
}
step();

手写promise

promise如何使用

js 复制代码
 const p0 = new Promise((resolve, reject) => {
   resolve(1);
 });
 
 p0.then(
   (res) => {console.log(res)},
   (err) => {console.log(err)}
 );

简单实现

js 复制代码
        function _Promise(fn){
            let _self=this
            _self.state='pending'
            _self.resolveAns
            _self.rejectAns
            function resolve(res){
                if(_self.state=='pending'){
                    _self.state='resolve'
                    _self.resolveAns=res
                }
            }
            function reject(res){
                if(_self.state=='pending'){
                    _self.state='reject'
                    _self.rejectAns=res
                }
            }
            try {
                fn(resolve,reject)
            } catch (error) {
                reject(error)
            }
        }
        _Promise.prototype.then=function(onResolve,onReject){
            let _self=this
            switch (_self.state) {
                case 'resolve':
                    onResolve(_self.resolveAns)
                    break;
                case 'reject':
                    onReject(_self.rejectAns)
                    break;
                default:
                    break;
            }
        }
        let p=new _Promise((resolve,reject)=>{
            resolve(1)
        })
        p.then((res)=>{
            console.log(res);
        })

异步实现

js 复制代码
function _promise(fn) {
  let _self = this;
  _self.state = "pending";
  _self.resolveAns;
  _self.rejectAns;
  _self.resolveAnsFn = [];
  _self.rejectAnsFn = [];

  function resolve(res) {
    if (_self.state == "pending") {
      _self.resolveAns = res;
      _self.state = "resolve";
      _self.resolveAnsFn.forEach((fn) => fn(res));
      _self.resolveAnsFn = [];
    }
  }
  function reject(res) {
    if (_self.state == "pending") {
      _self.rejectAns = res;
      _self.state = "reject";
      _self.rejectAnsFn.forEach((fn) => fn(res));
      _self.rejectAnsFn = [];
    }
  }
  try {
    fn(resolve, reject);
  } catch (error) {
    reject(error);
  }
}

_promise.prototype.then = function (resolveFn, rejectFn) {
  let _self = this;
  switch (_self.state) {
    case "resolve":
      resolveFn(_self.resolveAns);
      break;
    case "reject":
      rejectFn(_self.rejectAns);
      break;
    case "pending":
      _self.resolveAnsFn.push(resolveFn);
      _self.rejectAnsFn.push(rejectFn);
      break;
    default:
      break;
  }
};

let p = new _promise((resolve, reject) => {
  setTimeout(() => {
    resolve('111')
  }, 2000);
});
p.then((res) => {
  console.log(res);
});

链式调用

js 复制代码
// 自定义的Promise构造函数,用于模拟Promise的基本功能
function _Promise(fn) {
  const _self = this;
  _self.status = "pending";
  _self.resolveAns = undefined;
  _self.rejectAns = undefined;
  _self.resolveCallback = [];
  _self.rejectCallback = [];

  function resolve(res) {
    if (_self.status === "pending") {
      _self.status = "resolve";
      _self.resolveAns = res;
      _self.resolveCallback.forEach((fn) => fn());
      _self.resolveCallback = [];
    }
  }

  function reject(err) {
    if (_self.status === "pending") {
      _self.status = "reject";
      _self.rejectAns = err;
      _self.rejectCallback.forEach((fn) => fn());
      _self.rejectCallback = [];
    }
  }

  try {
    fn(resolve, reject);
  } catch (e) {
    reject(e);
  }
}

_Promise.prototype.then = function (resolveFn, rejectFn) {
  const _self = this;
  return new _Promise((resolve, reject) => {
    const callback = (fn) => {
      try {
          const result = fn(_self.resolveAns || _self.rejectAns);
          resolve(result);
      } catch (e) {
        reject(e);
      }
    };

    switch (_self.status) {
      case "resolve":
        callback(resolveFn);
        break;
      case "reject":
        callback(rejectFn);
        break;
      case "pending":
        _self.resolveCallback.push(() => callback(resolveFn));
        _self.rejectCallback.push(() => callback(rejectFn));
        break;
      default:
        break;
    }
  });
};
const p0 = new _Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
});

p0.then((res) => {
  console.log("监听p0 resolve状态的返回值", res);
  return res + 1;
}).then((res) => {
  console.log("监听p1 resolve状态的返回值", res);
}).then((res)=>{
    console.log(res);
})

修复then状态同步

js 复制代码
// 自定义的Promise构造函数,用于模拟Promise的基本功能
function _Promise(fn) {
  const _self = this;
  _self.status = "pending";
  _self.resolveAns = undefined;
  _self.rejectAns = undefined;
  _self.resolveCallback = [];
  _self.rejectCallback = [];

  function resolve(res) {
    if (_self.status === "pending") {
      _self.status = "resolve";
      _self.resolveAns = res;
      _self.resolveCallback.forEach((fn) => fn());
      _self.resolveCallback = [];
    }
  }

  function reject(err) {
    if (_self.status === "pending") {
      _self.status = "reject";
      _self.rejectAns = err;
      _self.rejectCallback.forEach((fn) => fn());
      _self.rejectCallback = [];
    }
  }

  try {
    fn(resolve, reject);
  } catch (e) {
    reject(e);
  }
}

_Promise.prototype.then = function (resolveFn, rejectFn) {
  const _self = this;
  return new _Promise((resolve, reject) => {
    const callback = (fn) => {
      try {
        const result = fn(_self.resolveAns || _self.rejectAns);
        if (result instanceof _Promise) {
          result.then(
            (res) => resolve(res),
            (err) => reject(err)
          );
          return;
        }
        resolve(result);
      } catch (e) {
        reject(e);
      }
    };

    switch (_self.status) {
      case "resolve":
        callback(resolveFn);
        break;
      case "reject":
        callback(rejectFn);
        break;
      case "pending":
        _self.resolveCallback.push(() => callback(resolveFn));
        _self.rejectCallback.push(() => callback(rejectFn));
        break;
      default:
        break;
    }
  });
};

const p0 = new _Promise((resolve, reject) => resolve());
p0.then((res) => {
  return new _Promise((resolve, reject) =>
    reject("p1 的 onResolved 里返回了新的 Promise,其状态是 rejected")
  );
}).then(
  (res) => {
    console.log("监听p1 resolved 状态的返回值");
    console.log(res);
  },
  (e) => {
    console.log("监听p1 rejected 状态的返回值");
    console.log(e);
  }
);

手写promiseAPI

all
js 复制代码
      Promise._all = function (promises) {
        let arr = [];
        return new Promise((resolve, reject) => {
          promises.forEach((item, i) => {
            Promise.resolve(item).then(
              (res) => {
                arr[i] = res;
                if (arr.length === promises.length) resolve(arr);
              },
              (e) => reject(e)
            );
          });
        });
      };

      let p1 = Promise.resolve("1");
      let p2 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("p2 延时一秒");
        }, 1000);
      });
      Promise._all([p1, p2]).then((res) => console.log(res));

any

js 复制代码
     Promise._any = function (promises) {
        count = 0;
        return new Promise((resolve, reject) => {
          promises.forEach((item, i) => {
            Promise.resolve(item).then(
              (e) => resolve(e),
              (err) => {
                count += 1;
                if (count === promises.length)
                  reject(new Error("没有promise成功"));
              }
            );
          });
        });
      };
race
js 复制代码
Promise._race = function (promiseArray) {
   return new Promise((resolve, reject) => {
     promiseArray.forEach(p => {
        Promise.resolve(p).then((res) => resolve(res), (err) => reject(err));
     })
   });
 }

let p3 = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("p3 延时一秒");
    }, 100);
  });

let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("p2 延时一秒");
  }, 1000);
});
Promise._race([p3, p2]).then((res) => console.log(res));

手写async await

async

js 复制代码
function reqData(url) {
  return new Promise((res, rej) => {
    setTimeout(() => {
      res(url);
    }, 2000);
  });
}
function* getData() {
  const r1 = yield reqData("why");
  console.log("r1:", r1);
  const r2 = yield reqData(r1 + "kobe");
  console.log("r2:", r2);
  const r3 = yield reqData(r2 + "james");
  console.log("r3:", r3);
}
const generator = getData()
  generator.next().value.then(res1 => {
      generator.next(res1).value.then(res2 => {
        generator.next(res2).value.then(res3 => {
          generator.next(res3)
        })
      })
    })
function exec(genFn) {
  const gen = genFn();
  function run(res) {
    const { done, value } = gen.next(res);
    if (done) return;
    value.then((res) => {
      run(res);
    });
  }
  run();
}
exec(getData);
相关推荐
deli0076 分钟前
32K 上下文塞满后,AI 最先忘掉什么?120 轮对话实测
前端
deli0071 小时前
手机拍灯为什么有一条条黑纹?PWM 240Hz 实测
前端
wangruofeng6 小时前
AI Models 1.1.0 发布,查大模型价格、对比模型和找 API 地址
前端·aigc·ai编程
wangruofeng6 小时前
给前端开发者的 100 个设计参考网站
前端·设计
星栈9 小时前
视频即代码,Remotion 能做什么、不能做什么
前端·音视频开发
广州华水科技9 小时前
单北斗GNSS位移监测系统的应用与技术解析
前端
用户47949283569159 小时前
从一句话或代码仓到可交互 HTML:开源 Agent 画图技能 Archify v3.2 实测与选型边界
前端·后端·面试
风骏时光牛马12 小时前
生成一个AI多模态标题,仅输出一条标题,无额外文字、问句、备选、配图、文案等任何附加内容,不需要其他的任务服务 只要标题。
前端
wangruofeng12 小时前
从 GIF 到 AVIF:网页图片格式演进与 2026 年选型指南
前端·架构
清晨Coding13 小时前
为什么用 React Developer Tools 查看组件树这么乱?
前端·react.js