我有以下两个函数,每个函数都返回一个Promise:
const getToken = () => {
return new Promise((resolve, reject) => {
fs.readFile('token.txt', (err, data) => {
if (err) { return reject(err) }
if (!tokenIsExpired(data.token)) {
return resolve(data.token)
} else {
return requestNewToken()
}
})
})
}
const requestNewToken = () => {
return new Promise((resolve, reject) => {
restClient.get(url, (data, res) => {
fs.writeFile('tokenfile.txt', data.token, err => {
resolve(data.token)
})
})
})
}
function1()
.then(value => {
console.log('taco')
})
.catch(err => {
console.log(err)
})
所以function1
运行,并且(取决于某些条件),它有时返回function2
,它返回另一个Promise。在此代码中,当调用function2
时,console.log('taco')
永远不会运行。为什么是这样?我认为如果你从Promise中返回一个Promise,嵌套Promise的解析值就是在顶级解析的。
为了让我能够使用它,我必须这样做:
const getToken = () => {
return new Promise((resolve, reject) => {
if (!tokenIsExpired()) {
return resolve(getToken())
} else {
return requestNewToken ()
.then(value => {
resolve(value)
})
}
})
}
这有效,但似乎我做错了什么。似乎应该有一种更优雅的方式来处理/构建它。
答案 0 :(得分:1)
你认为promises是自动解包的,但在这种情况下,你从promise构造函数中返回,这被忽略,你需要调用resolve
或{{1}而不是使用reject
。我认为这可能是您正在寻找的解决方案:
return
在promise构造函数中,您需要调用const function1 = () => {
return new Promise((resolve, reject) => {
if (someCondition) {
resolve('foobar')
} else {
resolve(function2());
}
})
}
或resolve
,这相当于在reject
回调中使用return
或throw
。
如果您发现这种区别令人困惑(我这样做),您应该完全避免使用承诺构造函数,只需使用then
开始一个新的链,如下所示:
Promise.resolve

使用更新的代码,我建议使用库来包装API,而不是自己访问promise构造函数。例如,使用bluebird' promisify:
const function1 = () => {
return Promise.resolve().then(() => {
if (someCondition) {
return 'foobar';
} else {
return function2();
}
})
}
const function2 = () => {
return new Promise((resolve, reject) => {
resolve('hello world')
})
}
someCondition = false;
function1()
.then(value => {
console.log(value)
})
我仍然忠实于您的源代码,但我注意到编写const bluebird = require('bluebird');
const readFile = bluebird.promisify(fs.readFile);
const writeFile = bluebird.promisify(fs.writeFile);
const getUrl = bluebird.promisify(restClient.get, {multiArgs:true});
const getToken = () => {
return readFile('token.txt')
.then((data) => {
if(!tokenIsExpired(data.token)) {
return data.token;
} else {
return requestNewToken();
}
});
};
const requestNewToken = () => {
return getUrl(url)
.then(([data, res]) => {
return writeFile('tokenFile.txt', data.token)
.then(() => data.token);
});
};
可能存在错误,之后尝试阅读data.token
属性那个文件。
为什么使用库而不是Promise构造函数?
token
函数抛出错误,使用您的promise构造函数代码,它将丢失。您需要将所有内部回调代码包装在tokenIsExpired
中,这很容易被遗忘。