NodeJs+Promise封装在一个函数中



我对NodeJ非常熟悉,我正在尝试对进行promise调用的函数进行调用,问题是在这种情况下,在进行API之前,recordId总是以未定义的形式返回。我在这里做错了什么?

var recordId = checkZoneRecord(zoneId, zoneName, dnsRecord);
console.log('Record id: %s', recordId)
if (recordId == ""){
// record doesn't exist, create new record
createZoneRecord (zoneId, zoneName, dnsRecord)
}else{
console.log ('Record name '%s' exists for zone '%s'', dnsRecord.name, zoneName);
}
function checkZoneRecord(zoneId, zoneName, dnsRecord){
// check if zone exists
cf.dnsRecords.browse(zoneId).then(function(resp){
console.log ('Checking if record name '%s' exists in zone '%s'', dnsRecord.name, zoneName);
var data = resp.result;
var rec = Enumerable.from(data).where(function(x){return x.name == dnsRecord.name + '.' + zoneName}).select(function(i){return i.id}).toJoinedString();
return rec;
}).catch(err => console.log(err));
}

我可以看到导致代码失败的两件主要事情:

  1. 您的checkZoneRecord函数从不使用return(默认情况下,没有return的函数将导致undefined(
  2. 在使用recordId的值之前,您不需要等待checkZoneRecord()调用完成

修复#1很容易!确保使用return:

function checkZoneRecord(zoneId, zoneName, dnsRecord){
// The only difference is to add "return" on this next line:
return cf.dnsRecords.browse(zoneId).then(function(resp){
/* ... */
return rec;
}).catch(err => console.log(err));
}

修复#2也很容易,但我们需要稍微改变一下。当以下代码运行时,您认为您正在记录"记录id",但您真正记录的是"承诺在未来某个时间解决记录id":

var recordId = checkZoneRecord(zoneId, zoneName, dnsRecord);
console.log('Record id: %s', recordId)

recordId变量的更好名称是recordIdPromise。幸运的是,一旦我们有了价值的承诺,转向价值本身就很简单了!有两种方法可以获得实际值:

// First, using `then`:
let recordIdPromise = checkZoneRecord(zoneId, zoneName, dnsRecord);
recordIdPromise.then(recordId => {
console.log(recordId);
});
// Second, using `await`.
// This looks easier, but the caveat is that this code will only work inside of an `async` function.
let recordIdPromise = checkZoneRecord(zoneId, zoneName, dnsRecord);
let recordId = await recordIdPromise;

值得一提的是,上面的片段可以简化为:

let recordId = await checkZoneRecord(zoneId, zoneName, dnsRecord);

以下是您的代码的外观,完全修复:


// Define all your logic in an `async` function called "app":
let app = async () => {
let recordIdPromise = checkZoneRecord(zoneId, zoneName, dnsRecord);
let recordId = await recordIdPromise;
console.log('Record id: %s', recordId)
if (recordId == ""){
// record doesn't exist, create new record
createZoneRecord(zoneId, zoneName, dnsRecord)
} else {
console.log ('Record name '%s' exists for zone '%s'', dnsRecord.name, zoneName);
}
};
// Define `checkZoneRecord`:
let checkZoneRecord = (zoneId, zoneName, dnsRecord) => {
// check if zone exists
return cf.dnsRecords.browse(zoneId).then(function(resp){
console.log ('Checking if record name '%s' exists in zone '%s'', dnsRecord.name, zoneName);
var data = resp.result;
var rec = Enumerable.from(data).where(function(x){return x.name == dnsRecord.name + '.' + zoneName}).select(function(i){return i.id}).toJoinedString();
return rec;
}); // I recommend you don't catch the err in this scope - let it propagate instead!
}
// Call `app`:
app().catch(err => console.log('An error occured', err));

最新更新