JavaScript:含异步回调的函数如何返回结果?IndexedDB实例解析
如何在带异步回调的JS函数中返回结果?
兄弟,你踩了JavaScript异步机制里最经典的坑!先给你说清楚为啥你的代码拿不到返回值:异步回调的执行时机比函数的return语句晚太多了。当你的get_info_tb函数走到return data那一行时,request.onsuccess这个回调根本还没执行,data变量要么没定义要么是undefined,自然返回不了你想要的结果。
下面给你三种常用的解决方案,从传统到现代语法都有:
方案1:使用回调函数(最传统的方式)
修改函数,让它接收一个回调参数,在异步操作成功/失败时调用这个回调传递结果:
function get_info_tb(callback) { var transaction = db.transaction(["mydb"]); var objectStore = transaction.objectStore("mydb"); var request = objectStore.get("01"); request.onerror = function(event) { // 失败时把错误传给回调 callback(new Error("Unable to retrieve data from database!"), null); }; request.onsuccess = function(event) { var data = request.result; // 成功时把数据传给回调 callback(null, data); }; } // 调用方式 get_info_tb(function(error, data) { if (error) { alert(error.message); return; } // 这里就能拿到异步返回的数据了 console.log("拿到的数据:", data); });
方案2:使用Promise(ES6+推荐方式)
把异步操作包装成Promise对象,用resolve传递成功结果,reject传递错误,这样可以用链式调用处理结果:
function get_info_tb() { return new Promise(function(resolve, reject) { var transaction = db.transaction(["mydb"]); var objectStore = transaction.objectStore("mydb"); var request = objectStore.get("01"); request.onerror = function(event) { reject(new Error("Unable to retrieve data from database!")); }; request.onsuccess = function(event) { var data = request.result; resolve(data); }; }); } // 调用方式:用.then处理成功,.catch处理失败 get_info_tb() .then(function(data) { console.log("拿到的数据:", data); }) .catch(function(error) { alert(error.message); });
方案3:使用async/await(ES8+语法糖,最接近同步写法)
这是基于Promise的语法糖,写起来像同步代码一样直观,但要注意必须在async标记的函数里使用await:
// 先复用上面的Promise版本get_info_tb函数 function get_info_tb() { return new Promise(function(resolve, reject) { var transaction = db.transaction(["mydb"]); var objectStore = transaction.objectStore("mydb"); var request = objectStore.get("01"); request.onerror = function(event) { reject(new Error("Unable to retrieve data from database!")); }; request.onsuccess = function(event) { var data = request.result; resolve(data); }; }); } // 调用时要放在async函数里 async function fetchMyData() { try { // await会等待Promise完成,拿到结果 var data = await get_info_tb(); console.log("拿到的数据:", data); } catch (error) { // 用try/catch捕获错误 alert(error.message); } } fetchMyData();
再给你理清楚异步机制的核心
JavaScript是单线程的,所有同步代码会先在主线程执行。像IndexedDB请求这种异步操作,会被放到任务队列里,等主线程的同步代码全部执行完(比如你的原函数里的return语句已经执行了),才会去处理任务队列里的回调函数。这就是为啥你原代码里的return拿不到data——回调还没跑呢!
内容的提问来源于stack exchange,提问作者Phuc Huynh
相关产品推荐
相关产品推荐

