Javascript 回调以确保异步api请求已完成

Javascript 回调以确保异步api请求已完成,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,我知道关于这个问题已经有几十万条线索了,我已经研究这个问题好几天了,但我仍然不知道如何将我所经历的例子应用到我的案例中 我从如下API调用开始: const getReleaseUrl = (discogsId) => { db.getRelease(discogsId, (err, data) => { return data.uri }) } console.log(getReleaseUrl("53130")); // => undefined 如

我知道关于这个问题已经有几十万条线索了,我已经研究这个问题好几天了,但我仍然不知道如何将我所经历的例子应用到我的案例中

我从如下API调用开始:

const getReleaseUrl = (discogsId) => { 
  db.getRelease(discogsId, (err, data) => {
    return data.uri
  }) 
}

console.log(getReleaseUrl("53130"));
// => undefined
如何确保我的应用程序首先接收数据,防止未定义的返回?我是否需要以某种方式确保
db
首先使用我的客户端id定义并连接到远程数据库?我是否需要编写一个函数,以某种方式捕获
未定义的
结果,并不断地运行API调用,直到结果有所不同?设置超时似乎不是一个好的永久解决方案。我试着写一个这样的承诺链,得到了
TypeError:db.getRelease(…)。那么这不是一个函数
错误:

const getReleaseUrl = (discogsId) => { 
  db.getRelease(discogsId, (err, data) => {
    return data
  })
  .then((data) => {
    return data.uri
  })   
}

console.log(getReleaseUrl("53130"));

看起来db.getRelease已经接受了回调,所以您可以在那里处理成功和错误

getReleaseUrl函数不返回任何内容。从arrow函数中删除大括号或添加return语句

使用承诺

var promise1 = new Promise(function(resolve, reject) {
resolve('Success!');
});

promise1.then(function(value) {
console.log(value);
// expected output: "Success!"
});
按照以下步骤操作:

请参见在
db.getRelease
之前添加的返回:

使用node.js
util
提示
db.getRelease

var util = require('util');
var getRelease = util.promisify(db.getRelease);
返回全部数据:

const getReleaseUrl = (discogsId) => {       
  return getRelease(discogsId); 
}
或返回特定的一个:

const getReleaseUrl = (discogsId) => {       
      return getRelease(discogsId)
             .then(function(data){ 
                  return data.uri;
             }); 
}        

按照这种编码方式,您的控制台消息不可能返回任何内容,除非
未定义

对于初学者,您的方法没有return语句。当然,回调有一个return语句,但这并不重要。没有返回语句,没有要记录的内容。使用您定义的方法,最好是在回调中放置一条控制台消息

const getReleaseUrl = (discogsId) => { 
  db.getRelease(discogsId, (err, data) => {
    console.log(data.uri);
    return data.uri
  }) 
}

getReleaseUrl("53130");
更好的替代方法是重写函数以接受回调作为参数:

const getReleaseUrl = (discogsId, callback) => { 
  db.getRelease(discogsId, callback);
}

getRelaseUrl("53130", (err, data) => {
  console.log(data.uri);
});

在这里,您正在将关于如何处理返回数据的逻辑移出主函数,这给了您更多的灵活性。它还确保在数据准备就绪之前不会调用日志消息。

您可以通过回调传递回调,也可以使用承诺。 让我们看看承诺选项:

const getReleaseUrl = (discogsId) => {
  return new Promise((resolve, reject) => {
    db.getRelease(discogsId, (err, data) => {
      if (err) {
        reject(err);
      }

      resolve(data);
    });
  });
};

getReleaseUrl("53130")
  .then(console.log);
  .catch(console.error);
问题是,正如您所说,对db.getRelease的调用是异步的,因此getReleaseUrl不会返回任何内容。
查看Pop-A-Stash的回答,找到一个回调选项。

它返回我的Discogs客户端数据,而不是
discogsId的音乐发布数据
是--它将返回你可以调用的承诺。然后(函数(数据){//access data here})我不得不取消选中你的回答,因为它毕竟对我来说不起作用。我有
var apiGetCall=util.promisify(db.getRelease(discogsId))
return apiGetCall
给出
的“原始”参数必须是Function类型的
error。无论最终使用回调、承诺还是异步/等待,都可能重复,请阅读对相关问题的回答,以了解发生了什么:@BrahmaDev该线程是一个很好的资源,我在开始该线程之前已经看到了它,但示例太广泛,我无法提出自己的解决方案k,但最终该逻辑将进入路由定义,它只需要返回值,没有控制台日志记录。我知道OP中的代码以控制台日志结尾,但这更多是为了查看代码输出的内容
console.log(getReleaseUrl('53130',(err,data)=>{return data.uri}))
再次给出undefined,当然它返回undefined。您必须了解异步函数与同步函数的工作方式不同。它们不返回直接值。您必须使用此回调模式或承诺。无论哪种方式,您都将定义一个稍后将被调用的函数。没办法。好吧,我现在明白了,但你的主要回复中没有解释