我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

本文还是继续总结promise相关代码的几种写法。如果总结的不是很好,大家也可以继续补充。本文里面的“显式”/“隐式”之类的说法,都是苏南大叔自己的名词,标准答案里面没有这样的说法。

苏南大叔:JavaScript,Promise异步函数相关写法方案总结 - promise异步写法
JavaScript,Promise异步函数相关写法方案总结(图1-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验文章。测试环境:chrome@131.0.6778.70nodejs@20.18.0。本文描述的是Promise相关函数的几种写法。

显式Promise(resolve)

显式的Promise,必须出现Promise关键字。一般的代表就是new Promise(resolve,reject)。参考代码:

const sunan_promise = new Promise((resolve, reject) => {
  let rand = Math.random();
  if (rand > 0.75) {
    resolve({ ok: true });
  } else if (rand > 0.5) {
    reject({ code: "-1", msg: "逻辑错误 Json Object" });
  } else if (rand > 0.25) {
    reject("自定义错误 String");
  } else {
    reject(new Error("意外错误 Error"));
  }
});

最简单的情况下,就是resolve()分支,并没有reject()的分支。因为如果写了reject()分支,外部就需要额外的catch()模块。

const sunan_promise = new Promise((resolve, reject) => {
  resolve({ ok: true });
});
// await sunan_promise;

很常见的写法中,会把它包裹在一个函数里面,return出去。

const sunan_promise_function = () => {
  return new Promise((resolve, reject) => {
    resolve({ ok: true });
  });
};
// await sunan_promise_function();

还有更简单的写法:

const sunan_promise_function_2 = () => {
  return Promise.resolve({ok:true});
};

隐式Promise(await)

隐式的Promise,必然是不出现Promise字样,但是却会被判定为promise类型。一般情况就是对promise进行包装的产物。例如上面的sunan_promisesunan_promise_function、包括系统函数fetch、第三方库axios等。

参考文章:

最简单情况

处理的方式是:使用await等待resolve()的返回值,外部使用async()await进行包裹。(特殊情况下,并不需要async字样,待议。)

参考代码:

const sunan_promise = new Promise((resolve, reject) => {
  resolve({ ok: true });
});
const sunan_promise_function = () => {
  return new Promise((resolve, reject) => {
    resolve({ ok: true });
  });
};
(async () => {
  let sn = await sunan_promise;
  console.log(sn);
  let sn2 = await sunan_promise_function();
  console.log(sn2);
})();

但是,这么写的前提是:全程只有resolve(),并没有reject(),否则就需要catch()模块。

需要catch()

如果内部有reject(),外部没有catch()模块,可能就会在一定概率下,得到下面的类似报错信息:

UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "自定义错误 String".

解决方式就是外部增加个catch()

const sunan_promise = new Promise((resolve, reject) => {
  let rand = Math.random();
  if (rand > 0.75) {
    resolve({ ok: true });
  } else {
    reject("自定义错误 String");
  }
});
(async () => {
  let sn = await sunan_promise.catch((e) => {
    return { code: -999, msg: e };
  });
  console.log(sn);
})();

e 还是 e.message

对于.catch()模块里面,如何获得内部传递出来的信息问题。其实,就看reject(ret)里面返回的是个啥。实际上是对ret进行解析的问题。所以,当它返回的是个new Error("string")的时候,就使用e.message来获取信息了。

const sunan_promise = new Promise((resolve, reject) => {
  let rand = Math.random();
  if (rand > 0.75) {
    resolve({ ok: true });
  } else {
    reject(new Error("自定义错误 String"));
  }
});
(async () => {
  let sn = await sunan_promise.catch((e) => {
    return { code: -999, msg: e.message };
  });
  console.log(sn);
})();

否则可能会得到[object object],或者带大段调试信息的内容。

{
  code: -999,
  msg: Error: 自定义错误 String
      at D:\test\test.js:6:12
      at new Promise (<anonymous>)
      at Object.<anonymous> (D:\test\test.js:1:23)
}

try catch

当然,也可以使用try catch来捕获里面的reject()信息,但是这样的话,报错信息和resolve()就是分开的了。不能统一的拿await拿到返回值了。

例如:

const sunan_promise = new Promise((resolve, reject) => {
  let rand = Math.random();
  if (rand > 0.75) {
    resolve({ ok: true });
  } else {
    reject(new Error("自定义错误 String"));
  }
});
(async () => {
  try{
    let sn = await sunan_promise;
    console.log(sn);
  }
  catch(e){
    console.log(e.message);
  }
})();

链式调用.then.then.catch.finally

就像yieldgenerator一样,.then.then.then也是可以一段一段执行的。例如response对象的.text().json()方法,它们实际上也是个promise,需要等待一下才能拿到结果。所以,可以使用多个.then组合对值进行加工。

(async () => {
  let ss = await fetch("https://localhost:3222/get")
    .then((response) => {
      return response.json();
    })
    .then((data) => {
      return data;
    })
    .catch((error) => {
      return { code: -999, msg: error.message };
    });
  console.log(ss);
})();

混合式promise

其实上边两种写法也可以放在一起使用。

const sunan_promise = new Promise((resolve, reject) => {
  fetch("http://localhost:3222/get")
    .then((response) => {
      if (!response.ok) {
        // 如果网络通的话,但是状态码有问题,可以走这里
        throw new Error("wrong status");
      }
      return response.json();
    })
    .then((data) => {
      resolve(data);
    })
    .catch((error) => {
      // 如果网络不通的话,可以直接走到这里
      reject(new Error(error.message));
    });
});
(async () => {
  let sn = await sunan_promise.catch((e) => {
    // 最终走这里
    return { code: -999, msg: e.message };
  });
  console.log(sn);
})();

结语

更多js的相关文章,请参考苏南大叔的博客文章:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   js