Est-ce que ce qui suit fonctionne? Il devrait selon le documentation.
const processValuesSerial = (v,process) => {
if(v === undefined){return Promise.resolve("nothing to do"); }
if(v.length === undefined){return Promise.resolve("nothing to do"); }
if(v.length === 0){return Promise.resolve("nothing to do"); }
if(v.length === 1){return process(Promise.resolve(v[0]),v[0]); }
return v
.map(x => Promise.resolve(x))
.reduce(process)
.then(//bug fix: last item was not processed
x=>
process(
Promise.resolve(x)
,Promise.resolve(v.slice(-1))
)
)
}
let keyword = 'horror games';
let kwOptions = {
qs: {
query: keyword,
},
url: "https://api.example.com/",
json: true
};
rp(kwOptions)
.then(function(relKeywords){
return processValuesSerial(
relKeywords[1]
,(acc, element) =>
acc
.then(x => {
console.log('searching for: ' + x);
//return promise like item from nightmare
return nightmare.evaluate(function() {
document.querySelector('input[cloom-label="query"]').setAttribute('value', ''); // Clear search box
})
.type('input[cloom-label="query"]', ' ' + x + '\u000d')
.click('span._5d a')
.wait(5000);
})
.then(x => element)
);
})
.catch(function(err){
console.log("Couldn't get keywords: "+err);
});
Conseils sur le débogage:
noeud de départ avec le débogage et des drapeaux briser:
node --inspect --debug-brk ./myscript.js
Ouvrir une nouvelle version de Google Chrome et accédez à about:inspect
Cette fenêtre contient une lien appelé Open dedicated DevTools for Node
, cliquez sur ce lien. Lorsque vous démarrez et arrêtez votre processus de noeud, le débogueur se reconnecte automatiquement. Lorsque vous commettez une erreur, vous pouvez voir où quelque chose s'est mal passé.
[mise à jour]
Avec le code suivant, vous pouvez jouer avec les promesses, il y a 2 façons de commencer le traitement des fonctions asynchrones:
- Démarrer tous à la fois
- Commencez le premier, attendez qu'il se termine, puis commencez le suivant
Certains commentaires sont ajoutés dans le code , vous pouvez exécuter ce code dans vos navigateurs devtools dans l'onglet console
//for each item in array v run process
// but only run the next item in v when the first item is resolved
var processValuesSerial = (v,process) => {
//checking valid imput
if(v === undefined){return Promise.resolve("nothing to do"); }
if(v.length === undefined){return Promise.resolve("nothing to do"); }
if(v.length === 0){return Promise.resolve("nothing to do"); }
//only one item, no need to reduce
if(v.length === 1){return process(Promise.resolve(v[0]),v[0]); }
//at least 2 items in v, process them
return v
.map(x => Promise.resolve(x))
.reduce(process)
//last item will not be passed to process function in reduce
// manually execute the last process function on this item
.then(
x=>
process(
Promise.resolve(x)
,Promise.resolve(v.slice(-1))
)
)
}
//functions that do something
var logValue =
(value,message) =>
//log value and return it
console.log(message,value) || value
//asynchronous function
var waitFor =
(howLong,returnValue) =>
//returning a promise that resolves after waiting for "howLong"
new Promise(
(resolve,reject)=>
setTimeout(x => resolve(returnValue),howLong)
)
;
//for each value I would like to do something asynchronous.
// for example
var values = [1,2,3,4,5];
/**
* Problem with promises is that they start immediately so the
* following example will start 1,2,3,4,5 imediately and then
* what we want is do(1).then(do(2)).then(do(3))
*/
Promise.all(
values.map(
x =>
Promise.resolve(x)
.then(
x => logValue(x,"+++++At the same time Starting:")
)
.then(
x => waitFor(x*500,x)
)
.then(
x => logValue(x,"+++++At the same time Finished:")
)
)
)
.then(x => console.log("finished promises at the same time"))
//the following will not start everything at the same time
// it will do(1).then(do(2)).then(do(3))
processValuesSerial(
values
//reducer function, acc is current value as a promise
// item is the next value as a promise
,(acc,item)=>
//acc is a promise that resolves to "item" (=1 then 2 then 3 then 4 then 5)
// the first time it is 1, the second time it is whatever we return here
// we return a promise
acc.then(
//acc is resolved so we should have a value of 1, then 2 ...
// if we return the right value
x=>logValue(x,"XXXXX In serie Starting:")
)
.then(
//return a promise that waits
x=>waitFor(x*500,x)
)
.then(
x=>logValue(x,"XXXXX In serie Finished:")
)
//return next item
.then(x=>item)
)
"OOOOOO Finished running synchronous code"
Je viens de mettre à jour la réponse, dans ma réponse, j'ai fait des choses en parallèle. Pour chaque élément de relKeywords [1] j'évalue, tape, clique et attend en même temps. La nouvelle réponse évaluera, tapera, cliquera et attendra, puis quand cela sera fait, elle évaluera, cliquera et attendra ... Je ne sais pas si ça marche parce que je n'ai aucun moyen de tester, il y aura une erreur quand relKeywords [1] est vide tableau. – HMR