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
的相关文章,请参考苏南大叔的博客文章:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。