gpt4 book ai didi

javascript - 如何在 Promise 中压平 Promise?

转载 作者:行者123 更新时间:2023-12-03 04:18:22 25 4
gpt4 key购买 nike

我有以下两个函数,每个函数返回一个 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)
})
}
})
}

这可行,但似乎我做错了什么。似乎应该有一种更优雅的方式来处理/构建这个。

最佳答案

你是对的, promise 自动解包,但在这种情况下,你从 promise 构造函数内部返回,该构造函数被忽略,你需要调用 resolvereject 而不是使用 return。我认为这可能是您正在寻找的解决方案:

const function1 = () => {
return new Promise((resolve, reject) => {
if (someCondition) {
resolve('foobar')
} else {
resolve(function2());
}
})
}

在 Promise 构造函数中,您需要调用 resolvereject,这相当于使用 returnthrow 来自 then 回调内部。

如果您发现这种区别令人困惑(我确实如此),您应该通过使用 Promise.resolve 开始一个新链来完全避免使用 Promise 构造函数,如下所示:

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)
})

对于更新后的代码,我建议使用库来包装 API,而不是自己访问 Promise 构造函数。例如,使用bluebird的promisify :

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 以及稍后尝试读取 token 可能会出现错误。该文件中的 code> 属性。

为什么使用库而不是 Promise 构造函数?

  • 它允许您编写仅处理 Promise 的代码,这(希望)更容易理解
  • 您可以确信回调 API 已正确转换而不会丢失错误。例如,如果您的 tokenIsExpired 函数使用您的 Promise 构造函数代码抛出错误,则该错误将会丢失。您需要将所有内部回调代码包装在 try {} catch(e) {reject(e)} 中,这很麻烦而且很容易被忘记。

关于javascript - 如何在 Promise 中压平 Promise?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44054467/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com