您引用的代码将同步运行。 JavaScript 函数调用是同步的。
所以我假设getData、parseData 和/或validate 涉及异步 操作(例如在浏览器中使用ajax,或在NodeJS 中使用readFile )。如果是这样,您基本上有两种选择,这两种选择都涉及回调。
首先是让这些函数接受它们在完成时将调用的回调,例如:
function getData(callback) {
someAsyncOperation(function() {
// Async is done now, call the callback with the data
callback(/*...some data...*/);
});
}
你会这样使用它:
getData(function(data) {
// Got the data, do the next thing
});
回调的问题在于它们很难组合并且具有相当脆弱的语义。因此发明了 promises 以赋予它们更好的语义。在 ES2015(又名“ES6”)或具有不错的 Promise 库中,它看起来像这样:
function getData(callback) {
return someAsyncOperation();
}
或者如果someAsyncOperation 没有启用承诺,那么:
function getData(callback) {
return new Promise(function(resolve, reject) {
someAsyncOperation(function() {
// Async is done now, call the callback with the data
resolve(/*...some data...*/);
// Or if it failed, call `reject` instead
});
});
}
似乎对你没有多大作用,但关键之一是可组合性;你的最终函数最终看起来像这样:
function runner() {
return getData()
.then(parseData) // Yes, there really aren't () on parseData...
.then(validate); // ...or validate
}
用法:
runner()
.then(function(result) {
// It worked, use the result
})
.catch(function(error) {
// It failed
});
这是一个例子;它只能在支持Promise 和 ES2015 箭头函数的相当新的浏览器上运行,因为我很懒,用箭头函数编写它并且没有包含 Promise 库:
"use strict";
function getData() {
// Return a promise
return new Promise((resolve, reject) => {
setTimeout(() => {
// Let's fail a third of the time
if (Math.random() < 0.33) {
reject("getData failed");
} else {
resolve('{"msg":"This is the message"}');
}
}, Math.random() * 100);
});
}
function parseData(data) {
// Note that this function is synchronous
return JSON.parse(data);
}
function validate(data) {
// Let's assume validation is synchronous too
// Let's also assume it fails half the time
if (!data || !data.msg || Math.random() < 0.5) {
throw new Error("validation failed");
}
// It's fine
return data;
}
function runner() {
return getData()
.then(parseData)
.then(validate);
}
document.getElementById("the-button").addEventListener(
"click",
function() {
runner()
.then(data => {
console.log("All good! msg: " + data.msg);
})
.catch(error => {
console.error("Failed: ", error && error.message || error);
});
},
false
);
<input type="button" id="the-button" value="Click to test">
(you can test more than once)