异步回调函数传值问题

如果调用的函数接受一个回调函数作为参数,那么怎么把回调函数获取的值传递出去呢?直接return是不可能做到的,本文探讨几种解决方案
/** * 创建一个项目 * @class * @param {number} id * @param {string} name * @param {string} desc */ function Project(id, name, desc) { this.id = id; this.name = name; this.desc = desc; } /** * 获取项目图片 * @param {number} id 项目编号 * @callback 请求结果 */ Project.prototype.getProjectImages = function (id, callback) { setTimeout(() => { var err = false; var res = `项目编号${id}的图片`; callback && callback(err, res); }, 2000); }; var project = new Project(1, "test", "test project"); var outter = '' project.getProjectImages(1, (err, res) => { if (err) { console.log("获取图片失败"); } else { console.log(res); // 项目编号1的图片 outter = res } }); console.log(outter) // ''

以上是初始代码,getProjectImages是一个异步函数,在打印outter时,这个异步函数还没有返回结果,因此打印的outter为空。下面来解决这个问题
使用回调函数
利用回调函数将结果传递出去
/** * 创建一个项目 * @class * @param {number} id * @param {string} name * @param {string} desc */ function Project(id, name, desc) { this.id = id; this.name = name; this.desc = desc; } /** * 获取项目图片 * @param {number} id 项目编号 * @callback 请求结果 */ Project.prototype.getProjectImages = function (id, callback) { setTimeout(() => { var err = false; var res = `项目编号${1}的图片`; callback && callback(err, res); }, 2000); }; var project_list = [ new Project(1, "java", "java项目"), new Project(2, "javascript", "javascript项目"), ]; function getImages(id, fn) { var index = project_list.findIndex((item) => item.id === id); var project = project_list[index]; project.getProjectImages(id, (err, res) => { if (err) { console.log("获取图片失败"); } else { fn(res); } }); } getImages(1, (imgs) => { console.log(imgs); // 项目编号1的图片 });

【异步回调函数传值问题】我们重新构建一个函数getImages,它接受必要参数和一个回调函数fn,利用这个回调函数传递异步函数执行结果
使用Promise(推荐)
/** * 创建一个项目 * @class * @param {number} id * @param {string} name * @param {string} desc */ function Project(id, name, desc) { this.id = id; this.name = name; this.desc = desc; } /** * 获取项目图片 * @param {number} id 项目编号 * @callback 请求结果 */ Project.prototype.getProjectImages = function (id, callback) { setTimeout(() => { var err = false; var res = `项目编号${1}的图片`; callback && callback(err, res); }, 2000); }; var project_list = [ new Project(1, "java", "java项目"), new Project(2, "javascript", "javascript项目"), ]; function getImages(id) { return new Promise((resolve, reject) => { var index = project_list.findIndex((item) => item.id === id); var project = project_list[index]; project.getProjectImages(id, (err, res) => { if (err) { return reject(err); } else { return resolve(res); } }); }); } getImages(1) .then((res) => { console.log(res); // 项目编号1的图片 }) .catch((err) => { console.log(err); });

上面使用Promise对异步回调的结果进行封装,这是解决许多现存库只支持异步回调不支持Promise的一般做法。resolve和reject不会直接返回,一般加上return
使用async/await改写
/** * 创建一个项目 * @class * @param {number} id * @param {string} name * @param {string} desc */ function Project(id, name, desc) { this.id = id; this.name = name; this.desc = desc; } /** * 获取项目图片 * @param {number} id 项目编号 * @callback 请求结果 */ Project.prototype.getProjectImages = function (id, callback) { setTimeout(() => { var err = false; var res = `项目编号${1}的图片`; callback && callback(err, res); }, 2000); }; var project_list = [ new Project(1, "java", "java项目"), new Project(2, "javascript", "javascript项目"), ]; function getImages(id) { return new Promise((resolve, reject) => { var index = project_list.findIndex((item) => item.id === id); var project = project_list[index]; project.getProjectImages(id, (err, res) => { if (err) { return reject(err); } else { return resolve(res); } }); }); }async function main() { var res = await getImages(1); console.log(res); } main();

    推荐阅读