[英]How to extract data out of a Promise
我有一個返回數據的 promise,我想將其保存在變量中。 由於異步性質,這在 JavaScript 中是不可能的嗎?我是否需要使用onResolve
作為回調?
我能以某種方式使用它嗎(例如用 async/await 包裝它):
const { foo, bar } = Promise.then(result => result.data, errorHandler);
// rest of script
而不是這個?
Promise.then(result => {
const { foo, bar } = result.data;
// rest of script
}, errorHandler);
注意:使用 Bluebird 庫而不是本機實現,我無法從 Promise 更改為 asnyc/await 或 Generators。
不,您不能像您在示例中建議的那樣從承諾中同步獲取數據。 數據必須在回調函數中使用。 或者,在函數式編程風格中,promise 數據可以被map()ed over 。
如果您可以使用async/await (您應該很棒),那么您可以編寫看起來同步但保留承諾的異步性的代碼(請參閱@loganfsmyth 評論)。
const { foo, bar } = await iAmAPromise.then(result => result.data);
總的來說,既然你已經在使用 ES6,我假設你也在使用轉譯器。 在這種情況下,您絕對應該嘗試async/await 。 只是一定要權衡決定,因為今天它們還沒有被批准的規范。
雖然您可以從異步函數中的等待 Promise 中獲取值(僅僅是因為它暫停函數以等待結果),但您永遠無法直接從 Promise 中獲取值並返回到與 Promise 本身相同的范圍內.
那是因為“out of”意味着嘗試將未來存在的東西(最終解決的值)放入過去已經發生的上下文(同步變量賦值)中。
也就是時間旅行。 即使時間旅行是可能的,它也可能不是一個好的編碼實踐,因為時間旅行可能會非常混亂。:)
一般來說,如果你覺得你需要這樣做,這是你需要重構某些東西的好兆頭。 請注意,您在此處使用“result => result.data”執行的操作:
Promise.then(result => result.data, errorHandler);
// rest of script
..已經是您通過將值傳遞給函數來處理(字面意思是映射)值的情況。 但是,假設“// 腳本的其余部分”做了與該值相關的重要操作,您可能希望使用另一個函數繼續映射現在更新的值,然后對該值執行一些副作用(例如顯示屏幕上的數據)。
Promise
.then(result => result.data)
.then(data => doSomethingWithData)// rest of script
.catch(errorHandler);
“doSomethingWithData”將在未來某個未知時間點被調用(如果它曾經被調用過)。 這就是為什么將所有這些行為清晰地封裝到一個特定的函數中,然后將該函數連接到 Promise 鏈上是一種很好的做法。
老實說,這種方式更好,因為它要求您清楚地聲明將發生的特定事件序列,明確地從第一次運行到所有應用程序代碼的執行中分離出來。
換句話說,想象一下這個場景,假設在全局頂級范圍內執行:
const { foo, bar } = Promise.then(result => result.data, errorHandler);
console.log(foo);
//...more program
你希望那里發生什么? 有兩種可能,而且都不好。
如果你願意,我有一個解決方案可以讓這個值“出來”。 這是后端的一種方法,用於將多個文件上傳到 AWS S3,必須異步處理。 我還需要來自 S3 的響應,所以我需要 Promise 中的值:
async function uploadMultipleFiles(files) {
const promises = []; //Creating an array to store promises
for (i = 0; i < files.length; i++) {
const fileStream = fs.createReadStream(files[i].path)
const uploadParams = {
Bucket: bucketName,
Body: fileStream,
Key: files[i].filename
}
promises.push(s3.upload(uploadParams).promise()) //pushing each promise instead
//of awaiting, to enable for concurrent uploads.
}
await Promise.all(promises).then(values => {
console.log("values: ", values) //just checking values
result = values; //storing in a different variable
});
return result; //returning that variable
}
與此處討論的問題相關的關鍵行是:
await Promise.all(promises).then(values => {
console.log("values: ", values) //just checking values
res = values; //storing in a different variable
});
return res; //returning that variable
但當然我們還必須等待 function 將調用它:
const result = await uploadMultipleFiles(files);
您需要做的就是使用 a.then 提取 promise 中的所有內容
yourFunction().then( resp => {
... do what you require here
let var1 = resp.var1;
let var2 = resp.var2;
...
.....
})
yourFunction() 應該返回一個 Promise
是的! 您可以從承諾中提取價值!
不要讓這里的任何人說你不能。 只要意識到存儲返回的 promise 值的任何變量都可能會有短暫的延遲。 因此,如果您有一個 JavaScript 腳本頁面需要 Promise 或異步等待函數之外的數據,您可能必須創建循環、間隔計時器或事件偵聽器以等待一段時間后獲取值。 因為大多數異步等待承諾是 REST 次調用並且速度非常快,所以等待只需要一個快速的 while 循環!
這很簡單,只需設置一個變量(或創建一個函數)來訪問異步或 promise 代碼中的值,並將該值存儲在 oitside 變量 object 數組中。 等你可以檢查:這是一個原始的例子:
// I just created a simple global variable to store my promise message.
var myDelayedData = '';
// This function is only used to go get data.
// Note I set the delay for 5 seconds below so you can test the delay
const getData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('my promise data'), 5000);
});
}
// I like to create a second async function to get the data
// from the promise object and save the data to my global variable.
const processData = async () => {
let data = await getData();
// Save the delayed data to my global variable
myDelayedData = data;
}
// Start the data call from the promise.
processData();
// Open up your browser, hit F12 to pull up the browser devtools
// Click the "console" tab and watch the script print out
// the value of the variable with empty message until after
// 5 seconds the variable is assigned to the resolved promise
// and apears in the message!
// THAT IS IT! Your variable is assigned the promise value
// after the delay I set above!
// TEST: But let's test it and see...
var end = setInterval(function(){
console.log("My Result: " + myDelayedData);
if(myDelayedData !== ''){
clearInterval(end);
}
}, 1000);
// You should see this in devtools console.
// Each line below represents a 1 second delay.
My Result:
My Result:
My Result:
My Result: my promise data
大多數人看到這段代碼會說“那為什么要使用 Promise,只是調用數據、暫停和更新您的應用程序?” 正確:Promise 的全部意義在於將數據處理封裝在 promise 中,並在腳本的 rest 繼續執行時執行操作。
但是......您可能需要 output Promise 之外的結果。例如,您可能有其他需要該數據的全局進程,因為它更改了全局應用程序的 state。 但至少您知道,如果需要,您可以獲得 Promise 數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.