JavaScript,Promise异步函数相关写法方案总结
发布于 作者:苏南大叔 来源:程序如此灵动~
本文还是继续总结promise相关代码的几种写法。如果总结的不是很好,大家也可以继续补充。本文里面的“显式”/“隐式”之类的说法,都是苏南大叔自己的名词,标准答案里面没有这样的说法。

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验文章。测试环境:chrome@131.0.6778.70,nodejs@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_promise和sunan_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
就像yield和generator一样,.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的相关文章,请参考苏南大叔的博客文章: