我想構建一個承諾,但推遲到稍後解決。下面的代碼創建了一個承諾,但它會立即解決。我如何控制何時獲得評估?解決承諾,在以後的時間
var p = new Promise((resolve, reject) => {
resolve(1);
})
.then((p1) => {
console.log(p1 + 1);
});
UPDATE:澄清,爲希望從它的執行所承諾的聲明分開的原因是添加動態then
回調,基於一些參數。
我想構建一個承諾,但推遲到稍後解決。下面的代碼創建了一個承諾,但它會立即解決。我如何控制何時獲得評估?解決承諾,在以後的時間
var p = new Promise((resolve, reject) => {
resolve(1);
})
.then((p1) => {
console.log(p1 + 1);
});
UPDATE:澄清,爲希望從它的執行所承諾的聲明分開的原因是添加動態then
回調,基於一些參數。
不完全確定你在問什麼 - 下面的代碼表明承諾的構造和調用then
以相同的順序發生,但可以在不同的時間執行。更改wait1
和wait2
的值,並查看輸出如何不同,但無論時間如何,代碼都能正常工作。
我認爲這將取決於您實施承諾代碼,以便它等待您想要等待的任何條件。在這個例子中,它是一個簡單的setTimeout
,但你可以想象做任何事情來推遲執行。
你可能需要使用Chrome看到這些結果在您的瀏覽器:
var wait1 = 2000;
var wait2 = 1000;
function log(...str) {
var li = document.createElement('li');
str.forEach((s) => {
li.appendChild(document.createTextNode(s));
});
document.getElementById("log").appendChild(li);
}
var p = new Promise((resolve, reject) => {
setTimeout(() => {
log("Resolving promise!");
resolve(1);
}, wait1);
});
log("Promise created!");
setTimeout(() => {
log("Calling 'then'");
p.then((p1) => {
log("Value:", p1 + 1);
});
}, wait2);
<ol id="log" />
不知道這是最好的方式,但您可以:
var resolve;
var promise = new Promise(function(fulfill) {
resolve = fulfill;
});
// now you can resolve the promise whenever you want
promise.then(function() {
console.log('done!');
});
resolve();
您可以將resolve
和reject
傳遞給您想要使用的任何異步功能。而這樣的功能可以在它完成工作時調用它。以下是Node中可運行的示例。如果您運行此操作,它將在當前目錄中執行ls -l
。 execSomething
函數只需要回調函數,而promiseToExec
函數將resolve, reject
回調函數傳遞到execSomething
,而不是立即調用其中任何一個。
const childProcess = require("child_process");
function execSomething(command, options, onSuccess, onError) {
childProcess.exec(command, options, (err, stdout, stderr) => {
if (err) {
onError(err);
}
onSuccess(stdout, stderr);
});
}
function promiseToExec(command, options) {
return new Promise((resolve, reject) => {
execSomething(command, options, resolve, reject);
});
}
promiseToExec("ls -l").then(console.log.bind(console));
Kazlauskis建議這樣做:
var resolve;
var promise = new Promise(function(fulfill) {
resolve = fulfill;
});
不要這樣做!。
當回調中發生異常時,您傳遞給new Promise
,承諾規範會自動將異常轉換爲承諾拒絕。所以如果回調裏面有任何東西throw Error...
,你會得到自動轉換。
如果您保存resolve
回調並將您的邏輯移到回調之外,那麼您將傳遞給new Promise
,那麼您不會獲得此自動轉換。在回調之外拋出的異常將被傳遞到堆棧,而不會被轉換爲承諾拒絕。這很糟糕,因爲它要求您的函數的用戶使用.catch
來捕獲拒絕的承諾和try...catch
以引發異常。這是一個糟糕的設計實踐。
這裏的代碼說明問題:
// This is how things should be done.
function makeGoodPromise(num) {
return new Promise((resolve) => {
if (num < 0) {
throw new Error("negative num");
}
resolve(num);
});
}
// This is a bad approach because it will sometimes result in synchronous
// exceptions.
function makeBadPromise(num) {
let resolve;
const p = new Promise((fullfil) => {
resolve = fullfil;
});
if (num < 0) {
throw new Error("negative num");
}
resolve(num);
return p;
}
// Shoring up the bad approach with a try... catch clause. This illustrates what
// you need to do convert the exception into a rejection. However, why deal with the
// additional scaffolding when you can just take the simpler approach of not
// leaking the callbacks??
function makeBadPromise2(num) {
let resolve, reject;
const p = new Promise((fullfil, deny) => {
resolve = fullfil;
reject = deny;
});
try {
if (num < 0) {
throw new Error("negative num");
}
resolve(num);
}
catch (e) {
reject(e);
}
return p;
}
makeGoodPromise(-1).catch(() => console.log("caught the good one!"));
try {
makeBadPromise(-1).catch(() => console.log("caught the bad one!"));
}
catch(e) {
console.log("Oops! Synchronous exception: ", e);
}
makeBadPromise2(-1).catch(() => console.log("caught the bad2 one!"));
當我在節點執行它,這是輸出:
Oops! Synchronous exception: Error: negative num
at makeBadPromise (/tmp/t12/test2.js:17:11)
at Object.<anonymous> (/tmp/t12/test2.js:48:3)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:394:7)
at startup (bootstrap_node.js:149:9)
caught the good one!
caught the bad2 one!
您需要決定如何以及爲什麼承諾將得到解決:沒有一般情況。實際上你很難直接做到這一點,因爲絕大多數async已經返回一個Promise,或者至少做一些你可以承諾的事情。經常感覺需要直接做這件事本身就是一個跡象,表明代碼中的某些東西需要重構。 – Dtipson