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);
相关推荐
凌乱的程序猿13 分钟前
安装和部署Tomcat并在idea创建web文件
java·前端·tomcat
DevSecOps选型指南1 小时前
SBOM情报预警 | 恶意NPM组件窃取Solana智能合约私钥
前端·npm·智能合约·软件供应链安全厂商·供应链安全情报
boring_student1 小时前
CUL-CHMLFRP启动器 windows图形化客户端
前端·人工智能·python·5g·django·自动驾驶·restful
SailingCoder1 小时前
递归陷阱:如何优雅地等待 props.parentRoute?
前端·javascript·面试
关山月2 小时前
React 中的 SSR 深度探讨
前端
yzhSWJ2 小时前
vue设置自定义logo跟标题
前端·javascript·vue.js
vvilkim3 小时前
Vue.js 中的 Tree Shaking:优化你的应用性能
前端·javascript·vue.js
杨超越luckly3 小时前
HTML应用指南:利用GET请求获取猫眼电影日票房信息——以哪吒2为例
前端·数据挖掘·数据分析·html·猫眼
狼性书生3 小时前
uniapp 实现的下拉菜单组件
前端·uni-app·vue·组件·插件
浪裡遊3 小时前
uniapp中的vue组件与组件使用差异
前端·vue.js·uni-app