2016-10-23 3 views
1

checkForURLSという複数の関数があり、コールバックを返す別の2つの関数を呼び出します。両方のコールバックが返された後、配列をコールバックとして返す方法はありますか?私は純粋なJavaScriptで作業しています。配列に複数のコールバック応答を追加

function checkForURLs(uniqueURL, customURL, callback) { 
    var errors = []; 

    checkForUniqueURL(uniqueURL, function(UniqueURLCallback) { 
     if (UniqueURLCallback===true) { 
      errors.push("This unique URL is already taken, please try another."); 
     } 
    }); 

    if (customURL.length>0) { 
     checkForCustomURL(customURL, function(customURLCallback) { 
      if (customURLCallback===true) { 
       errors.push("This custom URL is already taken, please try another."); 
      } 
     }); 
    } 

    if (errors.length>0) { 
     return callback(errors); 
    } else { 
     return callback(false); 
    } 
} 
+0

非同期機能との約束を扱うことの一例です。 checkForURLs(urlA、urlB、function(error){/ *コールバック関数でエラーを処理する* /}); '' 'を呼び出します。それはあなたが望むものではありませんか?なんでしょう? – Dario

+0

それは空に戻っているようですが、コールバック(エラー)を返すために内側のコールバックの1つにコールバックを置くと、その特定のコールバックのためだけに機能します。何が起こっているのかは、if文が待たずにただちに返ることです。 jQueryを使用すると、「完了」のようなものを使用して戻ってきた可能性がありますが、JavaScriptの使い方はわかりません。 –

+1

のように 'checkForUniqueURL()'のようなものは非同期であり、これはすべて約束を使って行うべきです。すべての関連コードを表示 – charlietfl

答えて

1

Promiseコンストラクタnew Promise(function),Promise.all()を使用して、checkForUniqueURLcheckForCustomURLコールバックが呼び出されたときにタスクを実行できます。

function callback(value) { 
 
    return value 
 
} 
 

 
function checkForUniqueURL(url, callback) { 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     resolve(callback(true)) 
 
    }, Math.random() * 1500) 
 
    }) 
 
} 
 

 
function checkForCustomURL(url, callback) { 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     resolve(callback(true)) 
 
    }, Math.random() * 1500) 
 
    }) 
 
} 
 

 
function checkForURLs(uniqueURL, customURL, callback) { 
 
    var errors = []; 
 

 
    return Promise.all([ 
 
    new Promise(function(resolve, reject) { 
 
     checkForUniqueURL(uniqueURL, function(UniqueURLCallback) { 
 
     if (UniqueURLCallback === true) { 
 
      errors.push("This unique URL is already taken, please try another."); 
 
     } 
 
     resolve() 
 
     }) 
 
    }) 
 
    , new Promise(function(resolve, reject) { 
 
     if (customURL.length > 0) { 
 
     checkForCustomURL(customURL, function(customURLCallback) { 
 
      if (customURLCallback === true) { 
 
      errors.push("This custom URL is already taken, please try another."); 
 
      } 
 
      resolve() 
 
     }); 
 
     } 
 
    }) 
 
    ]) 
 
    .then(function() { 
 
    console.log(errors); 
 
    if (errors.length > 0) { 
 
     return Promise.resolve(callback(errors)); 
 
    } else { 
 
     return Promise.reject(callback(new Error("false"))); 
 
    } 
 
    }) 
 
} 
 

 
checkForURLs("abc", "def", callback) 
 
    .then(function(errs) { 
 
    console.log(errs); 
 
    }) 
 
    .catch(function(err) { 
 
    console.log("err:", err.message) 
 
    })

+0

@PaulNess最新の記事を参照してください。 'resolve'を' if'文の外側に修正しました。以前は 'errors.length> 0'が' false'だった場合、 'reject()'は呼び出されませんでした。 – guest271314

0

あなたが使用するすべての機能が同期しており、次のように実装されている場合は、コードは完璧に動作します:

function checkForURLs(uniqueURL, customURL, callback) { 
 
    var errors = []; 
 

 
    checkForUniqueURL(uniqueURL, function(UniqueURLCallback) { 
 
     if (UniqueURLCallback===true) { 
 
      errors.push("This unique URL is already taken, please try another."); 
 
     } 
 
    }); 
 

 
    if (customURL.length>0) { 
 
     checkForCustomURL(customURL, function(customURLCallback) { 
 
      if (customURLCallback===true) { 
 
       errors.push("This custom URL is already taken, please try another."); 
 
      } 
 
     }); 
 
    } 
 

 
    if (errors.length>0) { 
 
     return callback(errors); 
 
    } else { 
 
     return callback(false); 
 
    } 
 
} 
 

 
// Just test-implement those two functions: 
 
function checkForUniqueURL(url, callback) { callback(true); } 
 
function checkForCustomURL(url, callback) { callback(true); } 
 

 

 
errors = checkForURLs("test", "test2", function(errors) { 
 
    console.log(errors); 
 
    return "I have got some errors!"; 
 
}); 
 

 
console.log(errors);

あなたのコードは、非同期の部分を持っている確かならば、あなたはreturn callback()で終了するまで待つ必要があります。他のコールバックでそれらをラップすることによって

0

あなたcheckForUniqueURLcheckForCustomURL機能が同期しているIFFこれは動作します。ここで私はそのが機能していないので、あなたの関数は非同期であることを、前提とするつもりだ...しかし

https://jsfiddle.net/ojh5b1f8/

同期機能をを働いての一例です。ここでは、コールバックの前にcheckForURLs関数リターンが発射されるので、それは動作しません

https://jsfiddle.net/uzjbyrt7/

... 非同期機能をを動作していないことの一例です。この場合の最適な解決策はPromisesです。ただし、すべてのブラウザではまだ実装されていないため、約束を得るためにライブラリを使用する必要があります。私はbluebird.jsをお勧めします。ここでは...あなたのコードが動作しなければならない

https://jsfiddle.net/ynxcu7t6/

関連する問題